Skip to main content

ROS 2 Router for Remote Robotics and Topic Filtering

· 19 min read
Dominik Nowak

At Husarnet, we’re streamlining ROS 2 networking across the Internet to be as easy and reliable as possible.

We're introducing the new husarnet/ros2router Docker image, which allows you to easily bridge ROS 2 nodes running across different robots, servers, or laptops in various networks. It features built-in topic filtering, enabling you to decide in real-time which ROS 2 interface should be exposed to remote hosts.

There's no need to change your DDS settings. Simply run our Docker image alongside your existing ROS 2 application, regardless of whether it's running on a host or inside Docker containers.

Discover how to integrate husarnet/ros2router with your robots, computers, or multi-tenant cloud applications and understand how it works in the following sections.

Husarnet ROS2Router cover

Quick start

Let's jump straight into the essentials. Suppose you want to connect your laptop and robot over the Internet. Here's the briefest guide to get you started:

TL;DR

1. Install Husarnet Client on Each Host

Execute the following command to install the Husarnet Client:

curl -s https://install.husarnet.com/install.sh | sudo bash

Then, set your Join Code as an environment variable (retrieve your Join Code from the online dashboard):

export JOINCODE=fc94:b01d:1803:8dd8:b293:5c7d:7639:932a/XXXXXXXXXXXXXXXXXXXXXX

Now, add your device to the Husarnet network with:

sudo husarnet join $JOINCODE my-laptop # or my-robot - choose the easy to remember hostname

2. Create filter.yaml on Each Host

You need a file to specify which ROS 2 topics are allowed. Only these topics will be permitted, all others will be blocked. Here's how you set up filter.yaml:

filter.yaml
allowlist:
- name: "rt/chatter"
type: "std_msgs::msg::dds_::String_"
blocklist: []
builtin-topics: []

3. Start the husarnet/ros2router on Each Host

Choose the appropriate version for ROS 2 Humble or ROS 2 Iron and run the following Docker command:

docker run --rm -d \
--name ros2router \
--net host \
--volume $(pwd)/filter.yaml:/filter.yaml \
--env ROS_LOCALHOST_ONLY=1 \
husarnet/ros2router:1.3.0

4. Run Your ROS 2 Nodes

To keep ROS 2 traffic local to your Husarnet network (which includes your laptop and robot), set the environment variables:

export ROS_LOCALHOST_ONLY=1

Then launch any ROS 2 nodes you like. For example, use the talker/listener demo from the demo_nodes_cpp ROS 2 package.

On host 1 (laptop), execute:

ros2 run demo_nodes_cpp talker

And on host 2 (robot), run:

ros2 run demo_nodes_cpp listener

5. Enjoy the Secure, Peer-to-Peer Connection

All done! Your ROS 2 devices are now connected over the Internet with traffic limited to those on the same Husarnet network. Additionally, you've successfully set up topic filtering to allow only the /chatter topic. Enjoy your secure, peer-to-peer ROS 2 setup.

What is ROS 2 Router?

A ROS 2 Router, also known as DDS Router, is an open source tool developed by eProsima as a solution to connect disparate DDS (Data Distribution Service) networks. This connectivity means you could, for instance, bridge a DDS network that relies on simple multicast discovery (the default in ROS 2) with a DDS network that operates using a Discovery Server setup or has a different ROS_DOMAIN_ID.

This flexibility is crucial in designing ROS 2 systems because it removes the limitation of having a uniform DDS configuration across your entire robotic fleet.

The router works by setting up separate participants for each DDS network you want to interconnect, with specific configurations for each.

An important feature of the ROS 2 Router is its ability to filter topics, giving you the capability to control which ROS 2 topics are visible or shared between networks. This ensures that only necessary information, like a robot's position, is available for monitoring, while sensitive or potentially harmful commands, such as /cmd_vel, remain private and secure.

Installation

Here’s how to install ROS 2 Router on a fresh Ubuntu 22.04 system, referencing the official guidelines:

apt update && apt install -y \
python3 \
cmake g++ pip wget git \
libyaml-cpp-dev \
libasio-dev libtinyxml2-dev

pip3 install -U \
colcon-common-extensions \
vcstool

mkdir -p ~/DDS-Router/src && cd ~/DDS-Router
wget https://raw.githubusercontent.com/eProsima/DDS-Router/main/ddsrouter.repos
vcs import src < ddsrouter.repos
colcon build

source ~/DDS-Router/install/setup.bash >> ~/.bashrc

Creating the Configuration File

Next, you'll want to create a configuration file for the ROS 2 Router:

ros2router-config.yaml
version: v3.0
allowlist:
- name: "rt/chatter"
type: "std_msgs::msg::dds_::String_"
blocklist: []
builtin-topics: []
participants:
- name: SimpleParticipant
kind: local
domain: 0
transport: udp
ignore-participant-flags: no_filter
whitelist-interfaces:
- 127.0.0.1
- name: RemoteParticipant
kind: initial-peers
listening-addresses:
- ip: fc94:1a20:95ec:f20a:02d3:9971:6f74:9874
port: 11811
connection-addresses:
- ip: fc94:b01d:18a3:8dc8:abd3:5c7d:7639:932a
port: 11811
- ip: fc94:4fef:2f42:4efe:e79a:d97d:af0a:d474
port: 11811
- ip: fc94:5fa1:c3f3:3abc:a87d:7485:23c4:ab45
port: 11811

This configuration includes:

  • A SimpleParticipant for the local, multicast-based DDS network typically used in ROS 2, limited to localhost (127.0.0.1).
  • A RemoteParticipant with a set of specified peers' Husarnet IPv6 addresses, to establish connections with remote DDS networks.

The allowlist and blocklist sections control which topics the ROS 2 Router can forward or should reject.

tip

For more detailed information on the configuration file format, the official documentation is a helpful resource.

Running the ROS 2 Router

To start the ROS 2 Router, simply execute:

ddsrouter -c ./ros2router-config.yaml

Streamlining ROS 2 Router Configuration with Husarnet

Managing a ROS 2 Router configuration file can be cumbersome and prone to errors. To address this, we’ve created a set of scripts for automation within an accessible husarnet/ros2router Docker image.

GitHub repo

Access the source code and releases for the husarnet/ros2router at our GitHub repository: Husarnet ROS 2 Router on GitHub.

This Docker image automates both the Husarnet and local configurations using environmental variables you provide. It interfaces with the Husarnet Client through its HTTP API.

Installing Husarnet

Before deploying the container, ensure Husarnet is installed on your devices (refer to the Husarnet installation guide):

curl -s https://install.husarnet.com/install.sh | sudo bash

Set your Join Code as an environment variable (obtain it from the Husarnet Dashboard):

export JOINCODE='your-join-code-here'

Join your device to the Husarnet network with:

sudo husarnet join $JOINCODE my-laptop # or my-robot - choose the easy to remember hostname
info

Integrating Devices from Different Husarnet Groups

For devices under the same Husarnet account but in different networks, consolidate them using the Online Dashboardor the Husarnet Dashboard CLI:

husarnet dashboard login
husarnet dashboard add my-robot my-network

Creating filter.yaml file

Implement topic filtering by creating a filter.yaml file with the desired allowlist, blocklist, and builtin-topics, such as:

filter.yaml
allowlist:
- name: "rt/chatter"
type: "std_msgs::msg::dds_::String_"
blocklist: []
builtin-topics: []

Launching husarnet/ros2router Docker Conatiner

Mount the filter.yaml file and run the Docker container:

docker run --rm -d \
--name ros2router \
--net host \
--volume $(pwd)/filter.yaml:/filter.yaml \
--env ROS_LOCALHOST_ONLY=1 \
husarnet/ros2router:1.3.0

The filter.yaml is dynamically merged with the auto-generated ROS 2 Router config, allowing you to modify it at runtime. Deploy the specified Docker image on each device you wish to interconnect, and it will bridge the local DDS networks across these devices automatically.

info

Environment Variables for husarnet/ros2router

To explore all the environmental variables that you can use with the husarnet/ros2router Docker image, visit the documentation provided here.

Proceed to operate your ROS 2 nodes on your host in the usual manner. For instance, you can use the talker/listener demo from the demo_nodes_cpp package in ROS 2 Humble.

For the first host, enter:

# This ensures that ROS 2 communication is routed 
# through the local DDS Router and not across the LAN
# if your hosts share the same local network.
export ROS_LOCALHOST_ONLY=1

ros2 run demo_nodes_cpp talker

On the second host, use:

export ROS_LOCALHOST_ONLY=1

ros2 run demo_nodes_cpp listener

Now, regardless of whether your hosts are situated in different local networks or on separate continents, you will observe that the ROS 2 traffic between them is seamlessly bridged.

Modes

The husarnet/ros2router Docker image serves as a versatile utility for a variety of configurations, catering to both on-host ROS 2 nodes and ROS 2 nodes within Docker environments.

With an auto-configured Husarnet setup, you can link remote hosts using either Initial Peers or Discovery Server Configurations:

  • Initial Peers setup: This configuration injects all detected Husarnet peer IPv6 addresses into the connection-addresses field within the Initial Peers (WAN) Participant. Optimal for straightforward ROS 2 networks, this mode supports an all-to-all communication pattern and is quite straightforward to implement.

  • Discovery Server setup: This configuration initializes a Discovery Server, enabling the Husarnet participant to function as a client, a server, or both concurrently. It effectively establishes a Local Discovery Server Participant, scaling better by minimizing discovery traffic.

Below you'll find detailed examples on how to execute both setups, including the necessary environment variables.

Initial Peers setup

Create a run.sh script with the following content:

run.sh
#!/bin/bash
if [[ "$ROS_DISTRO" == "iron" ]]; then
echo "ROS_DISTRO is set to iron"

docker run --rm -d \
--name ros2router \
--net host \
--env IGNORE_PARTICIPANTS_FLAGS=filter_different_host \
husarnet/ros2router:1.3.0

export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST
export ROS_STATIC_PEERS=127.0.0.1
else
echo "ROS_DISTRO is set to humble"

docker run --rm -d \
--name ros2router \
--net host \
--env ROS_LOCALHOST_ONLY=1 \
husarnet/ros2router:1.3.0

export ROS_LOCALHOST_ONLY=1
fi

# Run the corresponding ROS2 node based on the argument
ros2 run demo_nodes_cpp "$1"

Execute on the first ROS 2 host:

./run.sh talker

On the second host:

./run.sh listener

Discovery Server setup

Create a compose.client.yaml file with the following content for the server setup:

run_server.sh
#!/bin/bash
if [[ "$ROS_DISTRO" == "iron" ]]; then
echo "ROS_DISTRO is set to iron"

docker run --rm -d \
--name ros2router \
--net host \
--env DISCOVERY_SERVER_LISTENING_PORT=11811 \
--env DISCOVERY_SERVER_ID=0 \
--env IGNORE_PARTICIPANTS_FLAGS=filter_different_host \
husarnet/ros2router:1.3.0

export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST
export ROS_STATIC_PEERS=127.0.0.1
else
echo "ROS_DISTRO is set to humble"

docker run --rm -d \
--name ros2router \
--net host \
--env DISCOVERY_SERVER_LISTENING_PORT=11811 \
--env DISCOVERY_SERVER_ID=0 \
--env ROS_LOCALHOST_ONLY=1 \
husarnet/ros2router:1.3.0

export ROS_LOCALHOST_ONLY=1
fi

# Run the corresponding ROS2 node based on the argument
ros2 run demo_nodes_cpp "$1"

Run it with:

./run_server.sh talker

Exploring Various Setups for Discovery Server with husarnet/ros2router

The husarnet/ros2router Docker image is versatile, allowing ROS 2 nodes to operate in various environments: inside Docker containers, directly on the host operating system, or both. Configurations may vary depending on whether you use UDP connections between ROS 2 nodes and ROS 2 Router, or opt for a more efficient shared memory approach. Here we will examine different scenarios and configurations.

Focusing on the Discovery Server setup, let's look at the examples below.

Docker: UDP Setup

For Docker containers using a UDP connection:

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.3.0
network_mode: host
environment:
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0
- WHITELIST_INTERFACES=172.28.0.1

talker:
image: husarion/ros2-demo-nodes:humble
networks:
- network_talker
command: ros2 run demo_nodes_cpp talker

networks:
network_talker:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16

To run:

docker compose -f compose.server.yaml up
Utilizing the Default docker0 Network Interface

Rather than setting up a bespoke Docker network with a specific subnet for the purpose of appending to the WHITELIST_INTERFACES, the default docker0 network interface, which typically has the gateway address 172.17.0.1, can be employed.

Here is how you can set it up:

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.2.0
network_mode: host
environment:
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0
- WHITELIST_INTERFACES=172.17.0.1 # docker0 IP address

talker:
image: husarion/ros2-demo-nodes:humble
network_mode: bridge # using docker0 network interface
command: ros2 run demo_nodes_cpp talker

To ensure 172.17.0.1 is indeed your docker0 interface's gateway address, execute the following command:

ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1

This command extracts the IP address of the docker0 interface, which you can then verify against the gateway address specified in your Docker service configuration.

Docker: Shared Memory Setup

For a Docker setup with shared memory communication:

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.3.0
network_mode: host
ipc: host
environment:
- LOCAL_TRANSPORT=builtin
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0
- ROS_LOCALHOST_ONLY=1

talker:
image: husarion/ros2-demo-nodes:humble
network_mode: host
ipc: host
environment:
- ROS_LOCALHOST_ONLY=1
command: ros2 run demo_nodes_cpp talker

To run:

docker compose -f compose.server.yaml up

Host: UDP setup

For running directly on the host with a UDP connection:

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.3.0
network_mode: host
environment:
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0
- ROS_LOCALHOST_ONLY=1 # use it with ROS 2 Humble
# - IGNORE_PARTICIPANTS_FLAGS=filter_different_host # use it with ROS 2 Iron

To run:

docker compose -f compose.server.yaml up -d

export ROS_LOCALHOST_ONLY=1

# Run ROS2 listener
ros2 run demo_nodes_cpp talker

Host: Shared Memory setup

For a shared memory setup directly on the host:

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.3.0
network_mode: host
ipc: host
pid: host
user: ${MY_UID:-1000}:${MY_GID:-1000}
volumes:
- /etc/group:/etc/group:ro
- /etc/passwd:/etc/passwd:ro
- /etc/shadow:/etc/shadow:ro
environment:
- LOCAL_TRANSPORT=builtin
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0
- ROS_LOCALHOST_ONLY=1 # use it with ROS 2 Humble
# - IGNORE_PARTICIPANTS_FLAGS=filter_different_host # use it with ROS 2 Iron

To run:

export MY_UID=$(id -u)
export MY_GID=$(id -g)
docker compose -f compose.server.yaml up -d

export ROS_LOCALHOST_ONLY=1

# Run ROS2 listener
ros2 run demo_nodes_cpp talker
Enabling Exclusive Shared Memory Communication

The configuration outlined below ensures that ROS 2 nodes communicate solely via shared memory, bypassing UDP transport. This requires a precise setup using a custom DDS XML configuration file:

Create a file named localhost-shm-only.xml with the following content:

localhost-shm-only.xml
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>shm_transport</transport_id>
<type>SHM</type>
</transport_descriptor>
</transport_descriptors>

<participant profile_name="SHMParticipant" is_default_profile="true">
<rtps>
<userTransports>
<transport_id>shm_transport</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>

With this configuration, there's no need for ROS_LOCALHOST_ONLY or IGNORE_PARTICIPANTS_FLAGS environmental variables, as the local transport is set exclusively to shared memory, ensuring communication is localized to the host.

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.3.0
network_mode: host
ipc: host
pid: host
user: ${MY_UID:-1000}:${MY_GID:-1000}
volumes:
- /etc/group:/etc/group:ro
- /etc/passwd:/etc/passwd:ro
- /etc/shadow:/etc/shadow:ro
environment:
- LOCAL_TRANSPORT=shm
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0

To deploy the ROS 2 talker node through ROS 2 Router:

export MY_UID=$(id -u)
export MY_GID=$(id -g)
docker compose -f compose.server.yaml up -d

export FASTRTPS_DEFAULT_PROFILES_FILE=$(pwd)/localhost-shm-only.xml

# Run ROS2 talker
ros2 run demo_nodes_cpp talker

This localhost-shm-only.xml must be applied to every participant across all machines within the Husarnet network. Detailed instructions can be found in the DDR Router and Fast DDS documentation.

Host + Docker: Mixed Setup

For a mixed environment where some nodes run in Docker and some on the host:

compose.server.yaml
services:

ros2router:
image: husarnet/ros2router:1.3.0
network_mode: host
environment:
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0
- WHITELIST_INTERFACES=${DOCKER0_IP:-172.17.0.1};127.0.0.1

talker:
image: husarion/ros2-demo-nodes:humble
network_mode: bridge # using docker0 network interface
command: ros2 run demo_nodes_cpp talker

To run:

export DOCKER0_IP=$(ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)
nohup docker compose -f compose.server.yaml up

export ROS_LOCALHOST_ONLY=1

# just to make a time difference between two talkers
sleep 10

# Run ROS2 listener
ros2 run demo_nodes_cpp talker

Enhanced Client Connection Methods

The husarnet/ros2router in conjunction with a Discovery Server configuration offers a streamlined approach. It's important to note that deploying husarnet/ros2router on every host isn't necessary. For instance, each robot in your fleet can host its own husarnet/ros2router Docker container with the server setup, while your laptop or cloud system need not run it.

We will delve into how to employ the ROS_DISCOVERY_SERVER environment variable or create a custom XML file for a local DDS with SUPER_CLIENT settings in the upcoming sections.

Utilizing ROS_DISCOVERY_SERVER Env (Specific to ROS Iron)

For users of ROS 2 Iron, simply setting the ROS_DISCOVERY_SERVER environment variable is required. This variable can hold multiple discovery server addresses, delimited by semicolons (;). The server ID corresponds to the order in the list, starting with 0. An empty entry between semicolons denotes an available ID. For example, ROS_DISCOVERY_SERVER=";;abc:123;;;def:456" implies that the Discovery Server at abc:123 has an ID of 2, and the one at def:456 has an ID of 5.

note

Note on IPv6 Support in ROS_DISCOVERY_SERVER env:

  • ROS 2 Iron includes Fast-DDS version 2.10.2 and supports IPv6 addresses from Fast-DDS version 2.8.0.
  • ROS 2 Humble includes Fast-DDS version 2.6.6, which may not support this feature.
export ROS_DISCOVERY_SERVER=my-robot:11811

# Run ROS2 listener
ros2 run demo_nodes_cpp listener

Configuring FASTRTPS_DEFAULT_PROFILES_FILE Environment Variable

You can modify your local DDS settings to use a Discovery Server, bypassing the typical local multicast-based discovery. Here's what to include in your config file:

  • IPv6 address of the host running the Discovery Server "server" configuration within ROS 2 Router in the <address> section.
  • The designated port.
  • The remote server prefix determined by the DISCOVERY_SERVER_ID environment variable provided to husarnet/ros2router.
superclient.xml
<?xml version="1.0" encoding="UTF-8" ?>
<dds>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>HusarnetTransport</transport_id>
<type>UDPv6</type>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="client_profile" is_default_profile="true">
<rtps>
<userTransports>
<transport_id>HusarnetTransport</transport_id>
</userTransports>
<useBuiltinTransports>true</useBuiltinTransports>
<defaultUnicastLocatorList>
<locator>
<udpv6>
<address>husarnet-local</address>
</udpv6>
</locator>
</defaultUnicastLocatorList>
<builtin>
<discovery_config>
<discoveryProtocol>SUPER_CLIENT</discoveryProtocol>
<discoveryServersList>
<RemoteServer prefix="44.53.00.5F.45.50.52.4F.53.49.4D.41">
<metatrafficUnicastLocatorList>
<locator>
<udpv6>
<address>fc94:4fef:1952:4efe:579a:d97d:af0a:d474</address>
<port>11811</port>
</udpv6>
</locator>
</metatrafficUnicastLocatorList>
</RemoteServer>
</discoveryServersList>
</discovery_config>
</builtin>
</rtps>
</participant>
</profiles>
</dds>

After preparing the file:

export FASTRTPS_DEFAULT_PROFILES_FILE=$(pwd)/superclient.xml

# Run ROS2 node
ros2 run demo_nodes_cpp listener

For ease of use, the husarnet/ros2router can be employed to automatically generate the superclient.xml:

# Auto-generation of superclient.xml
docker run --rm -it \
--network host \
-e ROS_DISCOVERY_SERVER=my-robot:11811 \
-e DISCOVERY_SERVER_ID=10 \
husarnet/ros2router:1.3.0 \
cat /var/tmp/superclient.xml | awk '/\?xml version="1.0" encoding="UTF-8" \?/,0' > superclient.xml

export FASTRTPS_DEFAULT_PROFILES_FILE=$(pwd)/superclient.xml

# Run ROS2 listener
ros2 run demo_nodes_cpp listener

Initiating husarnet/ros2router

Though previously discussed, here's how to initiate the husarnet/ros2router to consolidate all methods in one section:

docker run --rm -d \
--network host \
--name ros2router \
-e ROS_DISCOVERY_SERVER=my-robot:11811 \
-e DISCOVERY_SERVER_ID=10 \
husarnet/ros2router:1.3.0

# Run ROS2 listener
ros2 run demo_nodes_cpp listener

Cloud Deployments

The previous sections assumed that Husarnet Client is running directly on the Host OS. If you want to run a multitenant cloud system, you may want to lauch a separate Husarnet Client, for each user and everything running on the same host.

To do so you can use Husarnet Sidecar Docker image. Below you will find the examples showing how to run Husarnet Client, ROS 2 Router and ROS 2 nodes totally in Docker:

compose.server.yaml
x-husarnet-net:
&husarnet-net
network_mode: service:husarnet-talker
ipc: service:husarnet-talker

services:

husarnet-talker:
image: husarnet/husarnet:2.0.180
ipc: shareable
networks:
- network_talker
volumes:
- /var/lib/husarnet
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
environment:
- HOSTNAME=talker
- JOINCODE
- HUSARNET_DEBUG=1

ros2router-talker:
image: husarnet/ros2router:1.3.0
<<: *husarnet-net
environment:
- LOCAL_TRANSPORT=builtin
- DISCOVERY_SERVER_LISTENING_PORT=11811
- DISCOVERY_SERVER_ID=0

talker:
image: husarion/ros2-demo-nodes:humble
<<: *husarnet-net
command: ros2 run demo_nodes_cpp talker

networks:
network_talker:
driver: bridge

To run the example execute:

export JOINCODE=... # copy here the joincode from app.husarnet.com
docker compose -f compose.server.yaml up

Note that in the Client setup in the ros2router-listener service there is:

depends_on: 
husarnet-listener: { condition: service_healthy }

Thanks to that ros2router will be started only when the talker host (launched in the Server setup) will be online. This is important because DDS Discovery Server IPv6 address is needed to be known before running clients connecting to it.

info

husarnet/husarnet Docker image includes the Docker healthcheck setting that return that the service is healthy only if all hosts listed in WAIT_HOSTNAMES env are available. This feature is used above.

Also note, that both ROS 2 Router and ROS 2 nodes in the example above are launched with network_mode: service:husarnet setting to share network namespace with a Husarnet service. The ipc: service:husarnet is used to enable a shared memory communication in DDS.

Using Husarnet Dashboard CLI

After you run the examples above you will have unnecessary talker and listener peers on your account at https://app.husarnet.com . You can remove them manually in the Online Dashboard or by using the CLI:

export HUSARNET_DASHBOARD_LOGIN=user@acme.com # your login to app.husarnet.com
export HUSARNET_DASHBOARD_PASSWORD=qwerty # your password to app.husarnet.com

husarnet dashboard login $HUSARNET_DASHBOARD_LOGIN $HUSARNET_DASHBOARD_PASSWORD

husarnet dashboard device remove talker
husarnet dashboard device remove listener

Conclusion

The husarnet/ros2router Docker image from Husarnet facilitates effortless ROS 2 networking by enabling connections between ROS 2 hosts over the Internet, circumventing complex DDS configurations and introducing efficient topic filtering capabilities. Deployable alongside existing ROS 2 nodes, either on the host or within Docker containers, husarnet/ros2router ensures seamless integration for bridging nodes across varied hosts online. Its adaptability extends to robots, laptops, and cloud environments with multi-tenant architectures, rendering it an optimal tool for topic-filtered communication within distributed robotic fleets.

COMMENTS

If you have any questions, or simply wish to share your thoughts regarding this blog post, check out this thread on the Husarnet Community Forum.