Host CLI for ROS OTA communication sessions.
Project description
ROS Communication DevContainer
The ROS Communication DevContainer is a Docker-based solution designed to streamline the bidirectional synchronization of ROS2 topics between two Linux machines. It provides built-in compression and routing capabilities for over-the-air (OTA) data transfer: selected topics are remapped into an OTA namespace and transmitted either via direct DDS (CycloneDDS) or through a Zenoh router. When desired, the session can also place local application nodes and OTA-facing bridge nodes into separate ROS 2 domain IDs and automatically generate a standard ROS 2 domain_bridge configuration for the /com/... boundary. This project aligns with the publication “Scalable Remote Operation for Autonomous Vehicles: Integration of Cooperative Perception and Open Source Communication.”
Key Features
- Minimal Dependencies: Only Docker is needed to get started, simplifying the setup process.
- Isolation: Operates in a separate Docker container, ensuring minimal impact on existing ROS setups.
- Centralized Configuration Management: All configurations are stored and managed in this repository.
- Compression: Built-in compression capabilities for efficient data transfer.
- QoS Configuration: Flexible Quality of Service settings for optimized communication.
Getting Started
Prerequisites
- Docker installed on all machines
- Git for configuration management
ros2dockerv0.1.2 or newer. The local installer below installs the pinned supported range into this checkout's virtual environment.- Machines connected to the same network (VPN or local WLAN)
Convenience CLI: rosotacom
This repository's main entrypoint for starting ROS communication sessions is
the checkout-local rosotacom command. Each checkout owns its own .venv,
so multiple rosotacom versions can coexist without global symlink drift.
Install
cd /path/to/ros_communication_devcontainer && ./install.sh
source .venv/bin/activate
rosotacom --version
python -m rosotacom --version
rosotacom doctor
Legacy global symlinks are still available when explicitly requested:
./install.sh --global-symlink
Basic Setup
rosotacom uses three layers of configuration/runtime state:
- A project setup file (
rosotacom.yaml) points to host-local resources such asros2docker.json, staticsessions/, ignoredsession-instances/, anddata_dict.json. - A session config defines the communication behavior for one run: peers, addresses, topics, QoS, processing, and transport choices.
- A session instance stores one concrete run: generated config, catmux pane logs, smoke debug output, and future rosbags.
No rosotacom.yaml is discovered automatically. Wire one explicitly with a flag or with ROSOTACOM_CONFIG:
rosotacom examples create ./rosotacom_examples
cd ./rosotacom_examples
eval "$(rosotacom setup-env ./rosotacom.yaml)"
rosotacom doctor
The copied packaged example project uses this layout:
rosotacom.yaml
ros2docker.json
data_dict.json
sessions/
session-instances/
scripts/
See the example project README for the copyable example layout.
The example data_dict.json uses 127.0.0.1 for both peers so the examples can run on one host and show how data:<key> references work. For two-machine runs, replace those values with each machine's reachable IP address or hostname.
Write or edit session configs under sessions/<name>/:
session-definition.yamlfor a self-contained sessionsession-parametrization.yamlfor a template plus parameters
Run rosotacom on each peer with the same active setup but a different identity:
# on peer "a"
rosotacom start 1_heartbeat_cyclone-ota --identity a
# on peer "b"
rosotacom start 1_heartbeat_cyclone-ota --identity b
rosotacom reads the static session input and creates generated files under session-instances/<date>/<session>_<timestamp>_<id>/config/, including per-peer plugin/session specs, topic lists, optional QoS, and optional domain_bridge.yaml. Catmux pane output is logged under the same instance in logs/<peer>/catmux/.
Usage Examples
Create and wire the example project first:
rosotacom examples create ./rosotacom_examples
cd ./rosotacom_examples
eval "$(rosotacom setup-env ./rosotacom.yaml)"
Run the local heartbeat smoke test:
rosotacom smoke
The smoke test verifies both directions through the communication path: it waits
for /com/in/a/heartbeat_a and /heartbeat_a in peer b, plus
/com/in/b/heartbeat_b and /heartbeat_b in peer a. For each checked topic it
also reports a SMOKE_METRIC line with the received rate (hz) and end-to-end
latency (delay_s) so rate and latency regressions are visible. It prints the
session-instances/... artifact path so failures (and the per-peer
logs/<peer>/catmux/... pane output) can be inspected after the containers stop.
Live status / debugging overview
Enable a continuously-updated, per-topic pipeline overview by setting
shared.use_status_overview: true in the session definition (see the
ready-made 1_heartbeat_status example). For every configured topic it tracks
where the topic currently is in the communication pipeline (furthest stage
reached and the first stage that is missing/broken), plus last-message age, Hz,
mean size, and latency.
The running session writes, under
session-instances/.../logs/<peer>/status/:
status.json— machine-readable snapshot (source of truth) for tools/agents, refreshed on a short interval and on every state transition,status.txt— a human-rendered table, andevents.jsonl— one line per state transition (when/where a topic stalled).
Read it from the host with the status command:
rosotacom status 1_heartbeat_status # human-readable table
rosotacom status 1_heartbeat_status --json # machine-readable, for tools/agents
rosotacom status 1_heartbeat_status --watch # live refresh
Phase 1 reports each peer's locally-observable stages (outbound up to the /ota
topic this peer publishes; inbound from the received /ota topic through the
republished application topic). Combine both peers' files for the full
end-to-end picture; cross-peer confirmation is reserved for a later phase.
Run the CI heartbeat smoke matrix locally:
just test-e2e-smoke
Run the heartbeat example manually:
./scripts/1_heartbeat/run_machine_a.sh
./scripts/1_heartbeat/run_machine_b.sh
For examples with external application containers, use the matching machine script directory. Example:
cd scripts/2_native_chatter/machine_a
./run_external.py
./run_communication.sh
The sessions/ directory contains the built-in session definitions:
1_heartbeat_fastdds: minimal heartbeat exchange over FastDDS1_heartbeat_cyclone-ota: heartbeat with CycloneDDS OTA config1_heartbeat_zen-endpoints: heartbeat with native Zenoh connected endpoints1_heartbeat_fastdds-local_cyclone-ota: local FastDDS with CycloneDDS OTA config1_heartbeat_cyclone-local_fastdds-ota: local CycloneDDS with FastDDS OTA1_heartbeat_cyclone-local_zenoh-ros2dds-ota: local CycloneDDS with Zenoh-ROS2DDS OTA2_native_chatter: bridge/chatterfrommachine_btomachine_a3_comp_occ_grid: compressed occupancy grid over DDS4_comp_occ_grid_zen: compressed occupancy grid through Zenoh5_sized_payload: sized payload test over DDS6_sized_payload_zen: sized payload test through Zenoh
Development
For contributor setup, local checks, PR workflow, CI, and releases, see CONTRIBUTING.md. CI behavior is summarized in docs/ci.md, releases in docs/release.md, and issue-driven work tracking in docs/work-items.md.
Choosing the Transport Layer: CycloneDDS or Zenoh
-
Use CycloneDDS when all machines share the same
ROS_DOMAIN_ID. This is the simplest and most direct configuration. -
Use Zenoh when peers cannot rely on one shared DDS domain, or when you want to split local application nodes and OTA-facing bridge nodes into different ROS 2 domains on each peer. In that split-domain setup this repository generates a standard ROS 2
domain_bridgefor/com/...topics locally, while Zenoh carries the/ota/...traffic between peers.
Position in the OTA Communication Landscape
This repository fits into a broader set of ROS-based OTA communication approaches:
-
Direct ROS 2 DDS Communication Native DDS (CycloneDDS, Fast DDS), often with custom configuration for constrained or long-range links. The examples in this repository use CycloneDDS to illustrate this approach.
-
ROS 2 over Router-like Backbones Some RMW have their own DDS Routers such as eProsima/DDS-Router. Example 4 uses Zenoh to act as a lightweight router layer.
-
MQTT-based Approaches Common in cloud/IoT scenarios. Example: ika-rwth-aachen/mqtt_client
-
Custom TCP/UDP Teleoperation Stacks Some frameworks implement their manual tcp/udp transportion layers. Example: TUMFTM/teleoperated_driving
How to Cite
If you wish to cite the ROS Communication DevContainer in your work, please use the following citation:
@InProceedings{gontscharow_scalable,
author = {Gontscharow, Martin and Doll Jens and Schotschneider, Albert and Bogdoll, Daniel and Orf Stefan and Jestram Johannes and Zofka, Marc and Z\"{o}llner, J. Marius},
title = {{Scalable Remote Operation for Autonomous Vehicles: Integration of Cooperative Perception and Open Source Communication}},
booktitle = {2024 IEEE Intelligent Vehicles Symposium (IV)},
year = {2024}
}
Acknowledgements
The research leading to these results was conducted within the project ÖV-LeitmotiF-KI and was funded by the German Federal Ministry for Digital and Transport (BMDV), grant number 45AVF3004A-G. Responsibility for the information and views set out in this publication lies entirely with the authors.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rosotacom-2.1.tar.gz.
File metadata
- Download URL: rosotacom-2.1.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98549663853b016b41ac76a0ddc156c061111d1eca1844b45e22f63cb2021e22
|
|
| MD5 |
02e8598bdcaa70799eef6b8c17014cb2
|
|
| BLAKE2b-256 |
da07d31a140c28dd70d5d24594dd7a3d3a90ca62acd230876104e90f7e807a57
|
Provenance
The following attestation bundles were made for rosotacom-2.1.tar.gz:
Publisher:
release.yml on develNor/ros_communication_devcontainer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rosotacom-2.1.tar.gz -
Subject digest:
98549663853b016b41ac76a0ddc156c061111d1eca1844b45e22f63cb2021e22 - Sigstore transparency entry: 1840934567
- Sigstore integration time:
-
Permalink:
develNor/ros_communication_devcontainer@a0633458f751bf5bec71d5f92eb47efbd0e4b905 -
Branch / Tag:
refs/tags/v2.1 - Owner: https://github.com/develNor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a0633458f751bf5bec71d5f92eb47efbd0e4b905 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rosotacom-2.1-py3-none-any.whl.
File metadata
- Download URL: rosotacom-2.1-py3-none-any.whl
- Upload date:
- Size: 476.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
430de52e3b2efc5f74c6adf2cc909ad24977b37d2c3cc4d7d7b8a609d539b389
|
|
| MD5 |
ec8f55b052e8279a77f24c5f2bdc57f9
|
|
| BLAKE2b-256 |
b2fb42d7f0e33f05b8ae369d3d9f2e42381ebbf947979a49bb953dca14cfee97
|
Provenance
The following attestation bundles were made for rosotacom-2.1-py3-none-any.whl:
Publisher:
release.yml on develNor/ros_communication_devcontainer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rosotacom-2.1-py3-none-any.whl -
Subject digest:
430de52e3b2efc5f74c6adf2cc909ad24977b37d2c3cc4d7d7b8a609d539b389 - Sigstore transparency entry: 1840934602
- Sigstore integration time:
-
Permalink:
develNor/ros_communication_devcontainer@a0633458f751bf5bec71d5f92eb47efbd0e4b905 -
Branch / Tag:
refs/tags/v2.1 - Owner: https://github.com/develNor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a0633458f751bf5bec71d5f92eb47efbd0e4b905 -
Trigger Event:
push
-
Statement type: