ROS 2 introduction
Chapter description
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.
These tutorials are 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 all ROSbots, and thanks to docker images, the necessary changes are simple and come down to launching the appropriate container, depending on your configuration.
Available ROSbot platforms:
You can find the repository containing the final result after completing all the ROS 2 Tutorials here.
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.
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
- Local
Connecting to the ROSbot with SSH
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. For both methods, you need an IP address of your robot. You can check it using one of the methods described in ROSbot - quick start tutorial.
To connect to your ROSbot via ssh type in the terminal:
ssh husarion@<ROSBOT_IP>
password is: husarion
Connecting to ROSbot with remote desktop
To use a remote desktop, you have to choose one of the following methods:
- Dockerized approach
- Client application
To set up Docker approach
, you need to follow the simple step-by-step guide, based on a remote-desktop repository.
- Check if your
DISPLAY
environment variable is set:
echo $DISPLAY
If the output is empty
- Find all available displays:
echo $(cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; break; done)
- Assign the output log from above (assume we have
:0
) toDISPLAY
variable and add this to~/.profile
file.
echo "DISPLAY=:0" >> ~/.profile
- Set up a password for a VNC session
export PASSWORD="husarion"
- Adjust the permissions for the X server host
xhost +local:docker
To persist the setting between boots, add the new line to
~/.profile
file"husarion@husarion:~$echo "xhost +local:docker" >> ~/.profile
- Run the container
docker run -d \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
-p 8080:8080 \
-e DISPLAY \
-e PASSWORD \
--ipc=host \
--restart=always \
--name=remote-desktop \
donowak/remote-desktop
- Open the following URL in your web browser on your local PC. Replace
IP_ADDR
with your ROSbot IP or Husarnet hostname:
http://IP_ADDR:8080/vnc_auto.html
To connect via remote desktop you need a remote desktop client application. Depending on your system, you may have various client apps.
Parameters for connection are the following:
protocol | `rdp` |
server | `xxx.xxx.xxx.xxx` |
username | `husarion` |
password | `husarion` |
If you are working on Windows, press WinKey + r
then type mstsc
.
You will see a window appear:
Type in your device IP address and click connect
. If you are working on
Mac, you can use Microsoft Remote Desktop available at AppStore.
If you are working on Ubuntu, you can use Remmina.
Regardless of the connection method you choose, the end result should be the same, and you should see the robot's 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:
- Create the workspace
mkdir -p rosbot_ws/src
cd rosbot_ws
- Clone
rosbot-ros
repository.
git clone https://github.com/husarion/rosbot_xl_ros.git src/rosbot_xl_ros
- Install tools.
sudo apt-get update
sudo apt install ros-dev-tools
- Install dependencies
vcs import src < src/rosbot_xl_ros/rosbot_xl/rosbot_xl_simulation.repos
sudo rosdep init
rosdep update --rosdistro humble
rosdep install -r --from-paths src --ignore-src --rosdistro humble -y
- Build and source your code.
source /opt/ros/humble/setup.bash
colcon build --symlink-install
echo 'source ~/rosbot_ws/install/setup.bash' >> ~/.bashrc
The last command ensures that whenever a new terminal is opened, the executables from rosbot_ws
is sourced.
- Launch simulation.
To speed up launching a simulator you can create alias in .bashrc
file. To do this type:
echo "alias ROSBOT_SIM='ros2 launch rosbot_xl_gazebo simulation.launch.py mecanum:=True camera_model:=intel_realsense_d435'" >> ~/.bashrc
. ~/.bashrc
ROSBOT_SIM
Coming soon
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.
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.
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 LaunchConfigurationEqualsNext, 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
Answer
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>
. To check available docker services use commanddocker compose config --services
, or find suitable Docker images prepared by Husarion.
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 have not already done so, configure your environment for simulations.
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.
Hint
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 rqt_image_view
located in the package with the same name.
Below there is a command to run rqt_image_view
node.
ros2 run rqt_image_view rqt_image_view
After that command new window should appear. Select appropriate topic to visualize. As the output, you should see the items in front of your camera.
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
Do you need any support with completing this tutorial or have any difficulties with software or hardware? Feel free to describe your thoughts on our community forum: https://community.husarion.com/ or to contact our support: support@husarion.com