Configuration Complexity
RC7 preparation: this page retains historical investigations and measurements, not approval of the current candidate. Runtime file contracts were checked against current source; historical interoperability, performance and platform claims were not remeasured by that review.
The pain
Getting DDS to work well in ROS 2 routinely means becoming a part-time DDS
network engineer (21 reports): hundreds of XML knobs, per-vendor dialects
(Fast DDS profiles vs Cyclone XML vs Connext QoS), kernel tuning (rmem_max,
ipfrag_*), and hidden prerequisites that are nearly impossible to find. The
shipped defaults are not the robotics-/WiFi-appropriate ones, so “good enough”
takes days of trial and error.
- Localhost-only mode silently requires multicast enabled on the loopback
interface (
ip link set lo multicast on) — undocumented in practice. - Selecting the right network interface, or making a Discovery Server introspectable, needs expert XML.
- A binary install can even go looking for a paid vendor by default.
Most recent example
ROS Discourse — “I’m done manually tuning DDS parameters!” (2026-04-30). A long, well-received thread: hundreds of knobs, days of trial-and-error, and still suboptimal results — a representative statement of the configuration-complexity tax.
Reference list (most recent)
| Date | Source | Problem |
|---|---|---|
| 2026-04-30 | ROS Discourse | “Done tuning DDS”: hundreds of knobs, days lost |
| 2025-12-09 | ROS Discourse | OSRF “Consolidated User Insights” on DDS pain |
| 2025-08-15 | ros2#1716 | Jazzy on Windows searches for paid RTI Connext |
| 2025-04-04 | rmw_cyclonedds#537 | failed to create domain, error Error |
| 2025-04-02 | cyclonedds#2201 | Network-interface selection requires config spelunking |
How ZeroDDS solves it
Robotics-appropriate defaults with explicit layered runtime files.
ros_defaults()works out of the box. A singleRuntimeConfig::ros_defaults()sets the representation offers (XCDR1 + XCDR2) and the 16 MiB reassembly cap ROS actually needs —rmw_zeroddsinterops with a real ROS 2 talker 20/20 with no XML and no environment tuning.- Runtime configuration is a typed base and ordered drop-ins.
Discovery uses
discovery.peers/discovery.no_multicast/transport.user_multicast, interface pinningtransport.interface. Later fragments override earlier values without copying the entire base. - Interface selection is one file setting. The “network-interface
selection” pain
(cyclonedds#2201)
is
transport.interface: <ip>, used for IP interface selection and advertised locators. SHM and Unix-domain sockets do not acquire an IP interface from this setting. - No hidden loopback prerequisite. Unicast localhost discovery does
not depend on multicast being enabled on
lo. - No paid-vendor fallback. The whole stack is open source (Apache-2.0 / MIT); there is no proprietary tier a default install can drift toward.
Why it no longer has to be a pain
Keep the project base under version control and add site-specific fragments. Explicit includes make shared settings visible. Invalid known runtime values fail before startup instead of silently falling back.
RC7 runtime files
The runtime standard path reads /etc/zerodds/zerodds.yaml, then YAML
fragments sorted by filename in /etc/zerodds/zerodds.d, then
/run/zerodds/zerodds.d. Missing implicit paths are allowed. Unreadable
or malformed files fail. Legacy runtime environment overrides no longer
select these values.
# /etc/zerodds/zerodds.yaml
discovery:
no_multicast: true
peers:
- 192.0.2.10
transport:
user_multicast: false
recv_batch: 32
# /etc/zerodds/zerodds.d/20-site.yaml
discovery:
+peers:
- 192.0.2.11
Replace the example addresses with reachable IPv4 addresses or
IPv4:port. include: shared.d includes another directory relative to
the including file. Nested directories require explicit includes.
Includes load before a file's own values. Maps merge, lists replace,
+peers appends. Use block lists, not inline lists. Cycles and invalid
includes fail.
Rust projects select a required base through
ConfigSource::from_path(path), including its sibling <stem>.d, then
the fallible RuntimeConfig::from_source. Explicit caller configuration
stays authoritative. RuntimeConfig::default() alone reads neither
files nor environment. ConfigSource::origins() reports surviving
scalar origins, including list elements.
This is the runtime schema, not every bridge schema. Bridge --config,
ROS selectors, explicit security APIs and vendor settings retain their
own contracts. Explicit variable interpolation remains supported.
Unknown application keys are not a fully validated application schema.
Executable source: runtime_config_layering.rs. Loader contract: zerodds-config README.
Reproduce it yourself
# Out-of-the-box ROS interop with no XML / no env tuning:
crates/ros2-rmw/interop/run_interop.sh # uses ros_defaults()
→ Back to overview · Next: Scaling
Konfigurations-Komplexität
RC7-Vorbereitung: Diese Seite enthält historische Untersuchungen und Messwerte, keine Freigabe des aktuellen Kandidaten. Die Runtime-Dateiverträge wurden mit dem aktuellen Quellstand abgeglichen; historische Interop-, Performance- und Plattformbehauptungen dadurch nicht erneut vermessen.
Der Schmerz
DDS in ROS 2 gut zum Laufen zu bringen heißt routinemäßig, ein Teilzeit-DDS-Netzwerk-Ingenieur zu werden (21 Reports): hunderte XML-Knöpfe, Per-Vendor-Dialekte (Fast-DDS-Profile vs Cyclone-XML vs Connext-QoS), Kernel-Tuning (rmem_max, ipfrag_*) und versteckte Voraussetzungen, die nahezu unmöglich zu finden sind. Die ausgelieferten Defaults sind nicht die robotik-/WiFi-passenden, sodass „gut genug” Tage von Trial-and-Error kostet.
- Localhost-Only-Modus erfordert still, dass Multicast auf dem Loopback-Interface aktiviert ist (
ip link set lo multicast on) — in der Praxis undokumentiert. - Das richtige Netzwerk-Interface zu wählen oder einen Discovery-Server introspizierbar zu machen, braucht Experten-XML.
- Ein Binary-Install kann sogar per Default nach einem bezahlten Vendor suchen.
Jüngstes Beispiel
ROS Discourse — „I’m done manually tuning DDS parameters!” (2026-04-30). Ein langer, gut aufgenommener Thread: hunderte Knöpfe, Tage von Trial-and-Error und immer noch suboptimale Ergebnisse — eine repräsentative Aussage über die Konfigurations-Komplexitäts-Steuer.
Referenzliste (jüngste zuerst)
| Datum | Quelle | Problem |
|---|---|---|
| 2026-04-30 | ROS Discourse | „Done tuning DDS”: hunderte Knöpfe, Tage verloren |
| 2025-12-09 | ROS Discourse | OSRF „Consolidated User Insights” zum DDS-Schmerz |
| 2025-08-15 | ros2#1716 | Jazzy auf Windows sucht nach bezahltem RTI Connext |
| 2025-04-04 | rmw_cyclonedds#537 | failed to create domain, error Error |
| 2025-04-02 | cyclonedds#2201 | Netzwerk-Interface-Auswahl erfordert Config-Spelunking |
Wie ZeroDDS es löst
Robotik-passende Defaults mit expliziten, geschichteten Runtime-Dateien.
ros_defaults()funktioniert out of the box. Ein einzigesRuntimeConfig::ros_defaults()setzt die Representation-Offers (XCDR1 + XCDR2) und den 16-MiB-Reassembly-Cap, die ROS tatsächlich braucht —rmw_zeroddsinteropt mit einem echten ROS-2-Talker 20/20 ohne XML und ohne Umgebungs-Tuning.- Runtime-Konfiguration besteht aus einer typisierten Basis und
sortierten Ergänzungen. Discovery nutzt
discovery.peers/discovery.no_multicast/transport.user_multicast, Interface-Pinningtransport.interface. Spätere Fragmente überschreiben frühere Werte, ohne die gesamte Basis zu kopieren. - Interface-Auswahl ist ein Dateiwert. Der
„Netzwerk-Interface-Auswahl”-Schmerz
(cyclonedds#2201)
ist
transport.interface: <ip>, für IP-Interface-Auswahl und angekündigte Locators. SHM und Unix-Domain-Sockets erhalten dadurch kein IP-Interface. - Keine versteckte Loopback-Voraussetzung.
Unicast-Localhost-Discovery hängt nicht davon ab, dass Multicast auf
loaktiviert ist. - Kein Paid-Vendor-Fallback. Der ganze Stack ist Open Source (Apache-2.0 / MIT); es gibt keinen proprietären Tier, zu dem ein Default-Install driften könnte.
Warum es kein Schmerz mehr sein muss
Die Projektbasis kann versioniert werden, standortspezifische Fragmente ergänzen sie. Explizite Includes machen gemeinsame Einstellungen sichtbar. Ungültige bekannte Runtime-Werte verhindern den Start, statt still durch Defaults ersetzt zu werden.
RC7-Runtime-Dateien
Der Standardpfad liest /etc/zerodds/zerodds.yaml, danach die nach
Dateinamen sortierten YAML-Fragmente in /etc/zerodds/zerodds.d, dann
/run/zerodds/zerodds.d. Fehlende implizite Pfade sind erlaubt;
fehlerhafte oder unlesbare Dateien verhindern den Start. Alte
Runtime-Umgebungsvariablen überschreiben diese Werte nicht.
# /etc/zerodds/zerodds.yaml
discovery:
no_multicast: true
peers:
- 192.0.2.10
transport:
user_multicast: false
recv_batch: 32
Beispieladressen durch erreichbare IPv4-Adressen oder IPv4:Port
ersetzen. Ein späteres Fragment kann mit discovery: und darunter
+peers: eine Liste ergänzen. include: shared.d bindet ein weiteres
Verzeichnis relativ zur Datei ein. Verschachtelte Verzeichnisse
benötigen explizite Includes. Includes werden vor den eigenen Werten
gelesen. Maps werden zusammengeführt, Listen ersetzt, +peers ergänzt
sie. Blocklisten verwenden. Zyklen und ungültige Includes werden
abgelehnt.
ConfigSource::from_path(path) verlangt eine Projektbasis und liest ihr
benachbartes <stem>.d; danach folgt RuntimeConfig::from_source.
Explizite Runtime-Konfiguration bleibt maßgeblich.
RuntimeConfig::default() liest weder Dateien noch Umgebung.
ConfigSource::origins() zeigt die Herkunft einzelner Werte.
Bridge---config, ROS-Selektoren, explizite Security-APIs und
Vendor-Konfiguration behalten eigene Verträge. Explizite
Variableninterpolation bleibt unterstützt; unbekannte
Anwendungsschlüssel sind kein vollständig validiertes Anwendungsschema.
Ausführbare Quelle: runtime_config_layering.rs. Loader-Vertrag: zerodds-config README.
Selbst reproduzieren
# Out-of-the-box-ROS-Interop ohne XML / ohne Env-Tuning:
crates/ros2-rmw/interop/run_interop.sh # nutzt ros_defaults()
→ Zurück zur Übersicht · Weiter: Scaling