ROS 2 Introduction
You will learn basic information about ROS 2 and what concepts are at the heart of each ROS 2 application. You will also become familiar with the ROSbot platform, which will be used for learning ROS 2. After setting up the environment, the first task will be to start and visualize the camera frames. The tutorial can be carried out both on the real platform and in the simulation.
Prerequisites
This tutorial series is dedicated for ROSbot XL equipped with LiDAR and camera. However, don't worry if your configuration is different or if you are using a different ROSbot. Most of the information and commands provided are compatible with ROSbot 2R/2 PRO, and thanks to Docker images, the necessary changes are simple and come down to launching the appropriate container, depending on your hardware configuration. It is also possible to solve the tutorial using the Gazebo simulation.
If you don't already own a ROSbot, you can get one from the Husarion store.
The tutorials are designed to flow sequentially and are best followed in order. If you're looking to quickly assess the content of a specific tutorial, refer to the ROS 2 Tutorials repository, which contains the completed outcomes.
What is ROS 2?
"The Robot Operating System (ROS) is a set of software libraries and tools for building robot applications. From drivers and state-of-the-art algorithms to powerful developer tools, ROS has the open source tools you need for your next robotics project.
Since ROS was started in 2007, a lot has changed in the robotics and ROS community. The goal of the ROS 2 project is to adapt to these changes, leveraging what is great about ROS 1 and improving what isn’t." ROS 2 webpage.
We have prepared a set of tutorials to help you start building advanced robots. These tutorials are designed to be performed on Husarion ROSbot XL, but they are also a valuable portion of knowledge for anybody interested in ROS 2.
System structure
ROS is a software suite that allows for quick and easy building of autonomous robotic systems. ROS should be considered as a set of tools for creating new solutions or adjusting already existing ones. A major advantage of this system is a great set of drivers and implemented algorithms widely used in robotics.
Nodes
The base unit in ROS is called a node. Nodes are in charge of handling devices or computing algorithms - each node for a separate task. Nodes can communicate with each other using topics or services. ROS software is distributed in packages. A single package is usually developed for performing one type of task and can contain one or multiple nodes.
Topics
In ROS, topic is a data stream used to exchange information between nodes. Topics are used to send frequent messages of one type, such as sensor readouts or information on motor goal speed. Each topic is registered under a unique name and with a defined message type. Nodes can connect to the topic to either publish messages or subscribe to them. For a given topic, one node can not publish and subscribe to it at the same time, but there are no restrictions on the number of different nodes publishing or subscribing.
Services
Communication through services resembles a client-server model. In this mode, one node (the server) registers a service in the system. Then, any other node can ask that service and get a response. In contrast to topics, services allow for two-way communication, as a request can also contain some data.
Visualization of this structure is taken from the official ROS 2 Documentation
ROSbot XL platform
This tutorial is created for ROSbot XL, an open-source robot platform, equipped with a camera and lidar. You can read more about it here: ROSbot XL.
Tutorials are prepared for a platform equipped with:
- 1 x Raspberry Pi 4
- 1 x LIDAR (e.g. RPLIDAR S2)
- 1 x RGBD camera (e.g. Intel D435)
In the basic configuration, ROSbot XL is equipped with:
- 1 x Digital Board based on STM32F407 microcontroller
- 1 x Power Board
- 4 x DC motor
- 1 x IMU sensor
- 1 x Li-Ion Batteries
- 1 x Antenna connected directly to a Wi-Fi module
- 1 x Speaker
And this is how it looks like:
You can also go through ROS 2 Tutorials using the Ignition Gazebo simulator environment instead of the physical robot. You can find the installation method in the next paragraph environment setup. If you want to use the simulation, you should have native ROS Humble installation that requires Ubuntu 22.04 operating system. Full guide can be found here.
We also created a package with all the nodes and launch files from our ROS 2 Tutorials. You can download ready to use pkg from GitHub page.
Environment setup
To get started with ROS, the simplest way is to connect via ssh to your ROSbot. It is also possible to test the functionality of ROS on your local computer by using the Gazebo simulator.
- ROSbot
- Simulation
Before you start working with ROS 2 on the ROSbot platform, you need to connect to your device first. You can establish the connection in two ways: using ssh
or via a remote desktop
. Instructions on how to connect to ROSbot:
- via ssh in the LAN, see How To Start
- via ssh over the Internet you will find in VPN Access
- using Remote Desktop
If you don't have a robot at hand, you can use the Gazebo simulator. There are two options for running the simulation.
- Native ROS Humble
- Dockerized approach
To get started with a native ROS Humble, please install ROS Humble on Ubuntu 22.04. Then you need to install additional dependency such as Husarion world. To do this follow below instruction:
1. Create the workspace and clone rosbot-ros
repository
mkdir -p rosbot_ws/src
cd rosbot_ws
git clone https://github.com/husarion/rosbot_xl_ros src/
2. Install tools and dependencies.
sudo apt-get update
sudo apt install ros-dev-tools
vcs import src < src/rosbot_xl/rosbot_xl_hardware.repos
vcs import src < src/rosbot_xl/rosbot_xl_simulation.repos
sudo rosdep init
rosdep update --rosdistro $ROS_DISTRO
rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y
3. Build and source your code.
export HUSARION_ROS_BUILD=simulation
source /opt/ros/humble/setup.bash
colcon build --symlink-install
4. Add source
command to .bashrc
- source the workspace every time a new terminal is opened.
echo 'source ~/rosbot_ws/install/setup.bash' >> ~/.bashrc
5. Create alias in .bashrc
file to speed up launching a simulator.
echo "alias ROSBOT_SIM='ros2 launch rosbot_xl_gazebo simulation.launch.py'" >> ~/.bashrc
. ~/.bashrc
6. Launch simulation.
ROSBOT_SIM
To get started with dockerized version follow the instructions below.
1. Clone rosbot-xl-docker
repository
git clone https://github.com/husarion/rosbot-xl-docker.git
cd rosbot-xl-docker/demo
2. Configure compose.
If you don't have Nvidia GPU go inside the compose.simulation.yaml
file and replace *gpu-config
with *cpu-config
in rosbot service right after <<:
sybmol.
3. Create alias in .bashrc
file to speed up launching a simulator.
echo "alias ROSBOT_SIM='xhost local:root && docker compose -f ~/rosbot-xl-docker/demo/compose.simulation.yaml up'" >> ~/.bashrc
. ~/.bashrc
4. Launch simulation.
ROSBOT_SIM
As the result you should see the following window.
Hello World - first steps in ROS 2
The first example of functionality will be running a basic talker
node from the demo_nodes_cpp
package. The sole purpose of this node is to display and send messages at a frequency of 1 Hz. The content of the message is of course Hello World
with a number specifying the number of messages sent. The message is also sent and can be received by other nodes or by tools. You'll get to know more about that in a moment. Now you'll learn two ways of running the code, using ros2 run
and ros2 launch
commands.
Execute node - ros2 run
Let's run your first node!
ros2 run demo_nodes_cpp talker
After running the command above, you should see something like this:
[INFO] [1681987653.420573969] [talker]: Publishing: 'Hello World: 1'
[INFO] [1681987654.420811998] [talker]: Publishing: 'Hello World: 2'
[INFO] [1681987655.420825802] [talker]: Publishing: 'Hello World: 3'
...
As we mentioned, the message is not only printed, but also sent and can be received by any other node. So let's launch another node from the demo_nodes_cpp
package named listener
. Launch a new terminal and type.
ros2 run demo_nodes_cpp listener
You should see the currently received message as the output
[INFO] [1681987653.420573969] [listener]: I heard: [Hello World: 11]
[INFO] [1681987654.420811998] [listener]: I heard: [Hello World: 12]
[INFO] [1681987655.420825802] [listener]: I heard: [Hello World: 13]
...
Details about ros2 run
Running nodes
Command ros2 run
allows you to run an executable in an arbitrary package from anywhere without having to give its full path. ros2 run
executes only one file. To start a new node, type ros2 run
and two more arguments: package_name
and node_type
, as shown below.
ros2 run package_name node_type [--ros-args options]
package_name
and node_type
are the names of package and node that you want to run. When using the ros2 run
command, the node is executed in the terminal, and text logs are displayed on the screen.
Parameters
ROS nodes take set of arguments that allow various properties to be reconfigured. Examples include configuring the name/namespace of the node, names of topic/service used, and parameters on the node. All ROS-specific arguments have to be specified after a --ros-args
flag.
Possible options
could be:
-
Remapping topic name - change the name of the topic subscribed or published by a node.
-r old_topic_name:=new_topic_name
-
Setting parameter
-p param_name:=param_value
-
Defining node - bind specific identifier to a node.
-r __node:=new_node_name
There are two underscores before the name. If you want to learn more about naming convention used by ROS 2 see ROS 2 documentation.
Execute nodes - ros2 launch
ros2 launch
is a tool that simplifies the running of multiple nodes at the same time. This tool uses launch
files which contain the configuration of all nodes to be run. Usage of ros2 launch
is simple and similar to the ros2 run
command. One key difference is that ros2 launch
can automatically start many nodes.
To execute the launch file type:
ros2 launch package launch_file [arguments]
or
ros2 launch launch_file [arguments]
The first one is for the case when you use the launch file provided with the package (you can run it from any folder). The second option is when you use a standalone launch file (you must run it in the folder where the launch file is located or point the path to it).
Structure of the launch
file
ROS 2 supports three different languages for writing the launch file. These can be Python, XML, or YAML. Below are examples that implement the same functionality as described in ros2 run
. In addition to starting the talker
and listener
nodes, we will also add a parameter that will allow us to decide when the listener
node will start. You can compare all the languages discussed below.
Let's create your first launch files!
- Python
- XML
- YAML
First, we need to create a new file called example.launch.py
. To do this we will use the text editor nano
. Create a new file with the following command:
nano example.launch.py
and paste the code visible below.
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument
from launch.conditions import LaunchConfigurationEquals
def generate_launch_description():
run_listener_arg = DeclareLaunchArgument("run_listener", default_value="true")
talker_node = Node(
package="demo_nodes_cpp", executable="talker", name="talker_node"
)
listener_node = Node(
package="demo_nodes_cpp",
executable="listener",
name="listener_node",
condition=LaunchConfigurationEquals("run_listener", "true"),
)
return LaunchDescription([run_listener_arg, talker_node, listener_node])
Press <ctrl + o>
and then <ctrl + x>
to save and quit.
Details about Python launch
The code explained
- These import statements pull in some Python launch modules.
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument
from launch.conditions import LaunchConfigurationEquals
- Next, we create function which must return LaunchDescription:
def generate_launch_description():
.
.
.
return LaunchDescription([...])
- Then we create an argument that will decide whether to start the listener.
run_listener_arg = DeclareLaunchArgument('run_listener', default_value='true')
- We set the nodes to run.
talker_node = Node(
package="demo_nodes_cpp", executable="talker", name="talker_node"
)
listener_node = Node(
package="demo_nodes_cpp",
executable="listener",
name="listener_node",
condition=LaunchConfigurationEquals("run_listener", "true"),
)
- The final action launches the mimic node with the remaps:
return LaunchDescription([run_listener_arg, talker_node, listener_node])
Configure nodes
-
For remapping the topic names add
remapping
argument inside theNode
constructor:Node(..., remappings=[("/old_name", "/new_name")])
-
For setting parameter add
parameters
argument inside theNode
constructor:Node(..., parameters=[{"parameter_name": parameter_value}])
First, we need to create a new file called example_launch.xml
. To do this, we will use the text editor nano
. Create a new file with the following command:
nano example_launch.xml
and paste the code visible below.
<launch>
<arg name="run_listener" default="true"/>
<node pkg="demo_nodes_cpp" exec="talker" name="talker_node"/>
<node if="$(var run_listener)" pkg="demo_nodes_cpp" exec="listener" name="listener_node"/>
</launch>
Press <ctrl + o>
and then <ctrl + x>
to save and quit.
Details about XML launch
The code explained
- File structure is defined in a markup language derived from XML and similar to HTML. Content of the
example_launch.xml
file is inserted between the start and end tags:<launch>...</launch>
(root element). Other elements including those that define nodes should be placed between them.
<launch>
.
.
</launch>
- Then we create an argument that will decide whether to start the listener.
<arg name="run_listener" default="true"/>
- We set the nodes to run.
<node pkg="demo_nodes_cpp" exec="talker" name="talker_node"/>
<node if="$(var run_listener)" pkg="demo_nodes_cpp" exec="listener" name="listener_node"/>
Configure nodes
-
For remapping the topic names use element
remap
and specify fieldsfrom
andto
:<remap from="/old_name" to="/new_name"/>
-
For setting parameter use element
param
and specify fieldsname
andvalue
:<param name="parameter_name" value="parameter_value"/>
First, we need to create a new file called example_launch.yaml
. To do this, we will use the text editor nano
. Create a new file with the following command:
nano example_launch.yaml
and paste the code visible below.
launch:
- arg:
name: "run_listener"
default: "true"
- node:
pkg: "demo_nodes_cpp"
exec: "talker"
name: "talker_node"
- node:
if: "$(var run_listener)"
pkg: "demo_nodes_cpp"
exec: "listener"
name: "listener_node"
Press <ctrl + o>
and then <ctrl + x>
to save and quit.
Details about YAML launch
The code explained
- Content of the
example_launch.yaml
file must startlaunch
world with:
at the end. Other elements including those that define nodes should start from-
and be placed below the first line.
launch:
- Then we create an argument that will decide whether to start the listener.
arg:
name: "run_listener"
default: "true"
- We set the nodes to run.
node:
pkg: "demo_nodes_cpp"
exec: "talker"
name: "talker_node"
node:
if: "$(var run_listener)"
pkg: "demo_nodes_cpp"
exec: "listener"
name: "listener_node"
Configure nodes
-
For remapping the topic names use element
remap
and specify fieldsfrom
andto
:remap:
- from: "/old_name"
to: "/new_name" -
For setting parameter use element
param
and specify fieldsname
andvalue
:param:
- name: "parameter_name"
value: "parameter_value"
There are many more possibilities that can be useful in more advanced systems. For more information, please visit the documentation, especially Launch file different formats
Execute launch file
As a reminder, to execute the launch file simply type ros2 launch
with a path to your launch file. If your launch files are in the same directory you can type.
- Python
- XML
- YAML
ros2 launch example.launch.py
Setup run_listener
parameters to false
.
ros2 launch example.launch.py run_listener:=false
ros2 launch example_launch.xml
Setup run_listener
parameters to false
.
ros2 launch example_launch.xml run_listener:=false
ros2 launch example_launch.yaml
Setup run_listener
parameters to false
.
ros2 launch example_launch.yaml run_listener:=false
You should get output similar to this:
Basic tools
ROS 2 has a lot of tools that allow you to quickly analyze running processes. Now you'll learn how to check available nodes and topics. For this we use two simple commands: ros2 node
and ros2 topic
.
Examining nodes - ros2 node
When you have talker
and listener
running, you can check all nodes that are running in the system. To do this, type in a in new terminal:
ros2 node list
As the output you should get:
/listener_node
/talker_node
This means, that you have now two nodes running: /talker_node
and /listener_node
. This command can be useful to check if all nodes are working. To check detailed information about a particular node, you can use the following command:
ros2 node info /talker_node
And as the output you should get:
/talker_node
Subscribers:
/parameter_events: rcl_interfaces/msg/ParameterEvent
Publishers:
/chatter: std_msgs/msg/String
/parameter_events: rcl_interfaces/msg/ParameterEvent
/rosout: rcl_interfaces/msg/Log
Service Servers:
/talker_node/describe_parameters: rcl_interfaces/srv/DescribeParameters
/talker_node/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
/talker_node/get_parameters: rcl_interfaces/srv/GetParameters
/talker_node/list_parameters: rcl_interfaces/srv/ListParameters
/talker_node/set_parameters: rcl_interfaces/srv/SetParameters
/talker_node/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
Service Clients:
Action Servers:
Action Clients:
The most important thing for you should be that the talker_node
actually publishes a message with the subject /chatter
and the type of that message is /std_msgs/msg/String
. In addition to the mentioned publisher, you can find many other interfaces that are typical for each node and are necessary for proper operation. An example may be services that allow reading or writing parameters (/talker_node/get_parameters
, rcl_interfaces/srv/SetParameters
).
Details about ros2 node
ros2 node
is a command line application for examining which nodes are registered in the system and also checking their statuses.
Using the application looks as follows:
ros2 node command [node_name]
command
could be:
list
- display list of running nodesinfo
- display info regarding selected node
For more information check ROS 2 documentation.
Examining topics - ros2 topic
Now we will check what topics are registered in the system and receive some info about them. In the new console type in:
ros2 topic list
You should get in the output:
/chatter
/parameter_events
/rosout
This means that you have three topics registered in the system. Let’s get some info about the first of them:
ros2 topic info /chatter
As the output you should get:
Type: std_msgs/msg/String
Publisher count: 1
Subscription count: 1
From that you can read, that via topic /chatter
only messages of type std_msgs/msg/String
can be transmitted. There is only one publisher (talker_node
) and one subscriber (listener_node
) to it.
Details about ros2 topic
ros2 topic
is a command line application for examining which topics are already being published and subscribed, checking details of the selected topic or reading messages being sent in it.
Using the application looks as follows:
ros2 topic command [topic_name]
The most useful command
could be:
list
- display list of topicsecho
- display messages published in the topicinfo
- display info regarding selected topichz
- displays the frequency of sending messages
For more information check ROS 2 documentation.
Examining system - rqt_graph
rqt_graph
is a graphical tool for the visualization of data flow across different nodes in the system. Thanks to this application, you can quickly visualize information about relationships between nodes - what topics are sent between them - and also receive the most important information about the topics such as: message type, message name and publication frequency.
Using the application looks as follows:
rqt_graph
There will be no response in the terminal, but a new window will appear. You will see:
Interpretation of the graph is as follows:
- ovals represent nodes,
- arrows represent topics
- rectangles containing other elements represent the namespace. For example, a stereo camera may have two nodes - one for each camera:
/camera/imageLeft
and/camera/imageRight
. In this case, all nodes containing the same shared part of the name will be inside the rectangle.
Question 1
Which command will you use to run 3 nodes at once?
a) ros2 run [node1] [node2] [node3]
b) ros2 launch
c) ros2 node
d) there is no possibility - each node should be run separately
Details
Answer
b)Task 1
Try renaming the topic name from /chatter
to /message
in any launch file. Check your solution using ros2 topic list
and ros2 topic echo
commands.
Starting camera
In this section, we will set up a ROS system that is equipped with an Orbbec Astra camera and show an image from the camera on display. Use remote desktop to connect to your ROSbot. You can also follow the tutorial in simulation mode using Gazebo and Husarion VM mentioned before.
- ROSbot
- Gazebo simulator
Running the camera on ROSbot is very simple thanks to the use of docker images. All you need to do is run the specified container.
docker compose up -d microros <rosbot_service> <camera_service>
Depending on your ROSbot model and specific configuration you should use an appropriate name for your
<rosbot_service>
and<camera_service>
. Check Husarion Docker to find suitable image.
For ROSbot XL with Astra camera, this command should look like this:
docker compose up -d microros rosbot-xl astra
Running the simulator is very easy thanks to the created aliases. If you haven't done so already check configure your environment.
ROSBOT_SIM
Task 2
Use ros2 node
and ros2 topic
tools to check if new nodes or topics appeared in the system. Next, find some info regarding new nodes and topics.
Details
View the camera image
Now using ros2 node list
we can see that the camera has started. To get a camera image preview, we can run another node called rviz2
located in the package with the same name.
Below there is a command to run rviz2
node.
rviz2
After that command new window should appear. Now you need to chose topic to visualize. Click Add -> By Topic -> Select your topic by name. For most of the camera we need to change QoS setting to Best Effort
. To do this click on expand Topic options and chose Readability Policy
Best Effort
.
For remote desktop
In case of an error, make sure to export the DISPLAY variable.
export DISPLAY=:0
It is recommended to put this line in .bashrc so that it will be executed automatically every time you run the terminal.
echo 'export DISPLAY=:0' >> ~/.bashrc
The frame rate can be slow because the whole image is transferred through the network. You will learn how to compress and speed up your system in one of the next tutorials.
Summary
After completing this tutorial you should know what are the basic components and tools of ROS 2.
You should know how to start nodes in two ways: using ros2 run
and ros2 launch
command, and how to set parameters and remap topic names in both scenarios.
You should also be able to check what nodes are running in the system and what topics are available, using the ros2 node
and ros2 topic
tools.
You are also familiar with rqt_graph
tool, and you know how to read information from it about the relationship between individual nodes.
by Rafał Górecki, Husarion
Need help with this article or experiencing issues with software or hardware? 🤔
- Feel free to share your thoughts and questions on our Community Forum. 💬
- To contact service support, please use our dedicated Issue Form. 📝
- Alternatively, you can also contact our support team directly at: support@husarion.com. 📧