In my previous post on Introduction to ROS, I shared how ROS is an extraordinary framework for robotics applications and is widely used in the industry of automated mobility, aka self-driving cars. ROS provides built-in libraries that can directly be used by importing them; one need not rewrite the entire code that someone else has already written. It is common to use ROS on multiple computers for the development of an automated system. These machines must work in harmony and the exchange between the ROS messages must function efficiently and proficiently.
In this blog, we will understand how to establish such communication between these machines that run in a ROS framework. Not only we will consider the case of ROS1-ROS1 communication but also the case of machines with different ROS distributions (ROS1-ROS2 communication). So boot up your Ubuntu machine (if you are using Windows, here’s a tutorial to install Linux on your computer and switch to Linux).
Table of Contents
Prerequisites
Before we start with establishing the communication, make sure that the computers involved are in the same network. Assume, we have a computer A with IP address 192.168.0.1 and a computer B with IP 192.168.0.2. [You can check these IPs by giving ifconfig
in the terminal]. We can check that both of them exist in the same network by pinging each other.
From computer A, try pinging computer B:
ping 192.168.0.2 # pinging computer B from A
Alternatively, you can check the same from computer B as follows:
ping 192.168.0.1 # pinging computer A from B
Now that both the stations we in the same network, we can start by setting up the communication.
ROS1-ROS1 Communication
Consider a scenario where computer A is the master publishing ROS topics and computer B is the client that is supposed to receive those topics.
To make ROS aware of this, we will declare as the following variables in our environment:
# on Computer A
export ROS_MASTER_URI=https://192.168.0.1:11311 # ip of computer A
export ROS_IP=192.168.0.1
Here, ROS_MASTER_URI
is the variable that informs ROS about the IP address of the master station and the port where the topics will be published (11311 in this case). Moreover, ROS_IP
is another variable in which the IP address of that computer is set, on which the particular ROS node is running.
Next, we move on to computer B where we will declare the same variable, i.e., computer A as our ROS master:
# on Computer B
export ROS_MASTER_URI=https://192.168.0.1:11311
Important Tip:
These variables are limited and recognized only in the terminal they are declared in. To make them global, write declare them directly into the bash script and source your bash script to update the environment. This way, everytime you open a terminal, the environment will declare those variables automatically.
# on Computer A
echo "export ROS_MASTER_URI=https://192.168.0.1:11311" >> ~/.bashrc
echo "export ROS_IP=192.168.0.1" >> ~/.bashrc
source ~/.bashrc
# on Computer B
echo "export ROS_MASTER_URI=https://192.168.0.1:11311" >> ~/.bashrc
echo "export ROS_IP=192.168.0.2" >> ~/.bashrc
source ~/.bashrc
Now we will start roscore
on computer A and start the talker
node in a new terminal:
# on computer A
roscore
# open a different terminal on computer A
rosrun roscpp_tutorials talker
If you receive any error that says something like “roscore command not found“, source your ROS configuration by typing source /opt/ros/$ROS_DISTRO/setup.bash
in the terminal. Your master station, i.e. computer A, in this case, will now start publishing topics. Let us check if computer B can receive this topic.
# on computer B
rostopic list
If everything till now has worked fine, then you should see the topic /talker
published from A. Subscribe to the topic as follows:
# on computer B
rosrun roscpp_tutorials listener
Now the terminal should echo the data from the topic. Congratulations! You just established a successful connection between two ROS1 stations.
But wait, it’s 2024! The support for any of the ROS1 distributions is no longer available. So many modern applications are built on ROS2 distribution like Humble. However, certain computing devices from well-known companies still use Ubuntu 18.04/20.04 as their base OS, and their SDK is dependent only on that older version of Ubuntu. This makes it impossible for developers to use their functionality without the older Ubuntu versions.
Thankfully, there exists a “bridge” that helps us build the communication between the older ROS1 and the newer ROS2. We will see this in the following section.
ROS1-ROS2 communication
For communication between ROS1-ROS2 machines, we need some bridge that converts the ROS1 topics into ROS2 format and vice versa. Fortunately, there exists a Docker image built on Ubuntu 20.04 called osrf/ros:foxy-ros1-bridge
. If you are new to Docker, I suggest you pause reading this blog here and have a look at this blog on Docker to gain a brief idea of how Docker works. It is quite straightforward and a trivial concept.
To understand the communication between these machines with different ROS distributions, we will again consider a scenario, this time with station R1 (for ROS1) and station R2 (for ROS 2). We will build a Docker container on R2 that listens to the topics published by station R1. The following illustrations represent this idea in a graphical form:
So first, we will pull the ROS1 bridge Docker image on R2:
# on station R2
docker pull osrf/ros:foxy-ros1-bridge
Run the docker image in an interactive mode and set the network as host. In the docker container, we will declare the R1 station as ROS master, similar to what we did previously.
# on station R2
docker run -it --net=host osrf/ros:foxy-ros1-bridge
# in the docker container:
export ROS_MASTER_URI=https://{R1-ip-address}:11311
This docker image contains two distributions for ROS, namely Noetic and Foxy. Thereby, we need to source both of them and ultimately start the dynamic_bridge
node of ros1_bridge
package:
# in the docker container:
source /opt/ros/noetic/setup.bash
source /opt/ros/noetic/setup.bash
ros2 run ros1_bridge dynamic_bridge --bridge-all-topics
Notice the argument --bridge-all-topics
! This is important as sometimes, the node ignores topics that have subscribers. Hence, to save computing power, the node ignores will not publish these topics. To avoid this, we pass the argument to allow all the topics on the bridge.
Start roscore
and the talker node on R1. In R2, outside the container, check if you receive any of the topics using ros2 topic list. If you see the topic published from R1, it means the bridge is working as intended and you are now ready to listen to the topic from R1 on R2, and process that data.
Summary
In this blog, we understood how to setup communication between two ROS machines. In case of both the machines having ROS1, you just need to set the IP of the master as the ROS master. Whereas, if both the machines run different ROS distributions, you can use the ROS Bridge Docker image and set the IP of the master as ROS master within that Docker container.
In case of any issues, feel free to reach out to me @machinelearningsite on Instagram. If you liked this blog, please do support by following me on my social media:
To stay updated with such latest blogs and posts in the fields of machine learning and programming, subscribe to my *FREE* monthly newsletter to receive updates on the newly published posts: