7
Command Line Tools

7.1 Setting the Environment

ROS relies on the notion of combining workspaces using the shell environment. 1 1 In this case, of course, it is our bash shell. The “workspace” is a ROS term for the location on our system where we’re developing with ROS .

  • the core ROS workspace is called the underlay,

  • and any subsequent local workspaces are called overlays.

When developing with ROS , we will typically have several workspaces active concurrently.

Combining workspaces makes developing against different versions of ROS , or against different sets of packages, easier. It also allows the installation of several ROS distributions 2 2 or “distros”, e.g. Dashing and Eloquent. on the same computer and switching between them. This is accomplished by sourcing setup files every time we open a new shell, or by adding the source command to our shell startup script once. Without sourcing the setup files, we won’t be able to access ROS commands, or find or use ROS packages.

In other words, we won’t be able to use ROS . To source, simply type the following:

bash
# Replace ".bash" with your shell if you're not using bash # Possible values are: setup.bash, setup.sh, setup.zsh source /opt/ros/humble/setup.bash

The exact command depends on where we installed ROS . Of course, if we have installed ROS using a docker container, this section can be skipped.

Sourcing the Script If we don’t want to have to source the setup file every time we open a new shell, then we can add the command to our shell startup script: 3 3 For our case it is .bashrc

bash
# Replace ".bash" with your shell if you're not using bash echo "source /opt/ros/humble/setup.bash" » ~/.bashrc

Checking Environment Variables Sourcing ROS setup files will set several environment variables necessary for operating ROS . If we ever have problems finding or using our ROS packages, make sure that our environment is properly set up using the following command:

bash
printenv | grep -i ROS

Information : The printenv Command

Displays the values of environment variables.

Using this command let’s check all variables like ROS_DISTRO and ROS_VERSION are set.

text
ROS_VERSION=2 ROS_PYTHON_VERSION=3 AMENT_PREFIX_PATH=/opt/ros/humble PYTHONPATH=/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages LD_LIBRARY_PATH=/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/aarch64-linux-gnu:/opt/ros/humble/lib ROS_LOCALHOST_ONLY=0 PATH=/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ROS_DISTRO=humble

If the environment variables are NOT set correctly, it might be worthwhile to reinstall ROS .

The ROS Domain ID Variable Once we have determined a unique integer for our group of ROS nodes, we can set the environment variable with the following command:

bash
export ROS_DOMAIN_ID=<your_domain_id>

To maintain this setting between shell sessions, we can also add the command to our shell startup script .bashrc :

bash
echo "export ROS_DOMAIN_ID=<your_domain_id>" » ~/.bashrc

Changing the Localhost Variable By default, ROS communication is NOT limited to localhost. 4 4 Localhost is a form of hostname, meaning the specific computer that the program is running on. It is employed as a method of connecting to services on the network on the physical host machine without the services of an outer network. When using “localhost”, we are connected to our computer or the node that is addressed by the IP address 127. Often used for testing and development, it lets developers run and test Web applications, or any other network service, locally before putting them on a live server. To summarize, it can be mentioned that localhost is the loopback network interface. ROS_LOCALHOST_ONLY environment variable allows us to limit ROS communication to localhost only.

This means our ROS system, and its topics, services, and actions will NOT be visible to other computers on the local network.

Using ROS_LOCALHOST_ONLY is helpful in certain settings, such as classrooms, where multiple robots may publish to the same topic causing strange behaviors. We can set the environment variable with the following command:

bash
export ROS_LOCALHOST_ONLY=1

Of course, to maintain it across different shell session we can write this command to our .bashrc :

bash
echo "export ROS_LOCALHOST_ONLY=1" » ~/.bashrc

7.2 Turtles and Graphs

Turtlesim is a great introduction to ROS as it is a lightweight simulator and easy to work on. It illustrates what ROS does at the most basic level to give us an idea of what we will do with a real robot or a robot simulation later on.

The ros2 tool is how the user manages, introspects, and interacts with a ROS system. It supports multiple commands which target different aspects of the system and its operation.

One might use it to start a node, set a parameter, listen to a topic, and many more.

The ros2 tool is part of the core ROS installation and should already be installed. This can easily be tested by typing ros2 into a terminal.

The second tool is rqt, a GUI tool for ROS .

Everything done in rqt can be done using CLI , but rqt provides a more user-friendly way to manipulate ROS elements.

We will work together to understand the fundamental concept which build the core of ROS , like nodes, topics, and services. All of these concepts will be elaborated on later.

For now, we will simply set up the tools and get a feel for them.

Installing the Required Packages In case of NOT having a configured docker container which was discussed in detail previously, please use the following commands to install all the necessary packages.

bash
sudo apt update sudo apt install ros-humble-turtlesim
text
0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.

To check if the package is installed, run the following command in the terminal:

bash
ros2 pkg executables turtlesim

which should return a list of turtlesim’s executable options:

text
turtlesim draw_square turtlesim mimic turtlesim turtle_teleop_key turtlesim turtlesim_node

Installing and Starting Turtlesim Let’s begin the tutorial by starting turtlesim:

bash
ros2 run turtlesim turtlesim_node

Under the command, we will see messages from the node. There we can see the default turtle’s name and the coordinates where it spawns.

text
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-ubuntu' [INFO] [1748967100.900464593] [turtlesim]: Starting turtlesim with node name /turtlesim [INFO] [1748967100.908647551] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

The simulator window should appear, with a random turtle in the centre. 5 PIC 5 Here we can see the turtlebot in its natural habitat, the turtlesim environment. The type of the turtle changes every time a new turtlesim environment is called. All these turtles represent a version of ROS .

Making the Turtle Move Around Now, open a new terminal and if it is NOT automatic, source ROS again. Now we will run a new node to control the turtle in the first node:

bash
ros2 run turtlesim turtle_teleop_key
text
Reading from keyboard --------------------------- Use arrow keys to move the turtle. Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation. 'Q' to quit.

At this point we should have three (3) windows open:

  • a terminal running turtlesim_node,

  • a terminal running turtle_teleop_key, and

  • the turtlesim window itself.

Let’s arrange these windows so we can see the turtlesim window, but also have the terminal running turtle_teleop_key active so that we can control the turtle in turtlesim using the arrow keys on the keyboard. It will move around the screen, using its attached “pen” to draw the path it followed so far.

Pressing an arrow key will only cause the turtle to move a short distance and then stop. This is because, realistically, we wouldn’t want a robot to continue carrying on an instruction if, for example, the operator lost the connection to the robot.

We can see the nodes, and their associated topics, services, and actions, using the list sub-commands of the respective commands:

bash
echo "~~ Node information ~~" && ros2 node list && echo "~~ Topic information ~~" && ros2 topic list && echo "~~ Service information ~~" && ros2 service list && echo "~~ Action information ~~" && ros2 action list
text
~~ Node information ~~ /teleop_turtle /turtlesim ~~ Topic information ~~ /parameter_events /rosout /turtle1/cmd_vel /turtle1/color_sensor /turtle1/pose ~~ Service information ~~ /clear /kill /reset /spawn /teleop_turtle/describe_parameters /teleop_turtle/get_parameter_types /teleop_turtle/get_parameters /teleop_turtle/list_parameters /teleop_turtle/set_parameters /teleop_turtle/set_parameters_atomically /turtle1/set_pen /turtle1/teleport_absolute /turtle1/teleport_relative /turtlesim/describe_parameters /turtlesim/get_parameter_types /turtlesim/get_parameters /turtlesim/list_parameters /turtlesim/set_parameters /turtlesim/set_parameters_atomically ~~ Action information ~~ /turtle1/rotate_absolute

Don’t worry about what this all means as we will have a detailed look into each of them in a later part.

Running rqt rqt is a GUI framework which implements various tools and interfaces in the form of plugins. If it is not installed on our system please run the following commands:

bash
sudo apt update sudo apt install '~nros-humble-rqt*'

Once installed, running it is pretty straightforward:

bash
rqt

When running rqt for the first time, the window will be blank. This is normal. To see what is currently going on just select Plugins/Services/Service Caller from the menu bar at the top. 6 PIC 6 The view of rqt with only turtlesim and teleop running.

Use the refresh button to the left of the Service dropdown list to ensure all the services of our turtlesim node are available. Once refreshed, click on the Service dropdown list to see services belonging to turtlesim, and select the /spawn service.

Working the the spawn service Let’s use rqt to call the /spawn service. We can guess from its name that /spawn will create another turtle in the turtlesim window.

Give the new turtle a unique name, like turtle2, by double-clicking between the empty single quotes in the Expression column. We can see that this expression corresponds to the value of name and is of type string.

Next enter some valid coordinates at which to spawn the new turtle, like x = 1.0 and y = 1.0.

If we try to spawn a new turtle with the same name as an existing turtle, like the default turtle1, we will get an error message in the terminal running turtlesim_node.

To spawn turtle2, we then need to call the service by clicking the Call button on the upper right side of the rqt window.

If the service call was successful, we should see a new turtle, again with a random design. spawn at the coordinates we input for x and y.

If we refresh the service list in rqt, we will also see that now there are services related to the new turtle, turtle2, in addition to turtle1.

Changing the Trail Parameters Now let’s give turtle1 a unique pen using the /set_pen service:

PIC

(a) The parameters of the /set_pen service.

PIC

(b) The trail line of turtle1 has changed

The values for r, g, and b, which are between 0 and 255, set the colour of the pen turtle1 draws with, and width sets the thickness of the line.

To have turtle1 draw with a distinct red line, change the value of r to 255, and the value of width to 5.

Don’t forget to call the service after updating the values.

If we were to return to the terminal where turtle_teleop_key is running and press the arrow keys, we will see turtle1 ’s pen has changed and also noticed that there’s no way to move turtle2. That’s because there is no teleop node for turtle2.

Remapping Controls We need a second teleop node in order to control turtle2. However, if we try to run the same command as before, we will notice that this one also controls turtle1. The way to change this behavior is by remapping the cmd_vel topic.

To do that, In a new terminal, source ROS , and run:

bash
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle

Now, we can move turtle2 when this terminal is active, and turtle1 when the other terminal running turtle_teleop_key is active.

7.3 A Deeper Look into Nodes

Each node in ROS should be responsible for a single , modular purpose . 7 7 e.g., controlling the wheel motors or publishing the sensor data from a laser range-finder. Each node can send and receive data from other nodes using:

  • topics,

  • services,

  • actions, or

  • parameters.

A full robotic system is comprised of many interconnected nodes working in unison. In ROS , for example, a single executable 8 8 C++ program, Python program, etc. can contain one or more nodes.

ros2 run Now let’s put all this knowledge into motion. The command ros2 run launches an executable from a package.

bash
ros2 run <package_name> <executable_name>

To run turtlesim, open a new terminal ( Ctrl + Alt + T ), and enter the following command:

bash
ros2 run turtlesim turtlesim_node

Here, the package name is turtlesim and the executable name is turtlesim_node. We still don’t know the node name, however.

ros2 node list We can find node names by using ros2 node list, which will show us the names of all running nodes. This is especially useful when we want to interact with a node, or when we have a system running many nodes and need to keep track of them.

Open a new terminal while turtlesim is still running in the other one , and enter the following command. The terminal will return the node name:

bash
ros2 node list
text
/turtlesim

Open another new terminal and start the teleop node with the command:

bash
ros2 run turtlesim turtle_teleop_key

Here, we are referring to the turtlesim package again, but this time we target the executable named turtle_teleop_key.

Return to the terminal where we ran ros2 node list and run it again. We will now see the names of two active nodes:

bash
ros2 node list
text
/turtlesim /teleop_turtle

Remapping a Node Remapping allows us to reassign default node properties:

like node name, topic names, service names, etc., to custom values.

Previously, we have used remapping on turtle_teleop_key to change the cmd_vel topic and target turtle2.

Now, let’s reassign the name of our /turtlesim node. In a new terminal, run the following command:

bash
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle

Since we’re calling ros2 run on turtlesim again, another turtlesim window will open. However, now if we return to the terminal where we ran ros2 node list, and run it again, we will see three (3) node names:

text
/my_turtle /turtlesim /teleop_turtle

ros2 node info Now that we know the names of our nodes, we can access more information about them with:

bash
ros2 node info <node_name>

To examine our latest node, my_turtle, run the following command:

bash
ros2 node info /my_turtle
text
/my_turtle Subscribers: /parameter_events: rcl_interfaces/msg/ParameterEvent /turtle1/cmd_vel: geometry_msgs/msg/Twist Publishers: /parameter_events: rcl_interfaces/msg/ParameterEvent /rosout: rcl_interfaces/msg/Log /turtle1/color_sensor: turtlesim/msg/Color /turtle1/pose: turtlesim/msg/Pose Service Servers: /clear: std_srvs/srv/Empty /kill: turtlesim/srv/Kill /my_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters /my_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes /my_turtle/get_parameters: rcl_interfaces/srv/GetParameters /my_turtle/list_parameters: rcl_interfaces/srv/ListParameters /my_turtle/set_parameters: rcl_interfaces/srv/SetParameters /my_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically /reset: std_srvs/srv/Empty /spawn: turtlesim/srv/Spawn /turtle1/set_pen: turtlesim/srv/SetPen /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute /turtle1/teleport_relative: turtlesim/srv/TeleportRelative Service Clients: Action Servers: /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute Action Clients:

ros2 node info returns a list of subscribers, publishers, services, and actions. 9 9 i.e., the ROS graph connections that interact with that node.

Now try running the same command on the /teleop_turtle node, and see how its connections differ from my_turtle.

7.4 Working with Topics

ROS breaks complex systems down into many modular nodes. Topics are a vital element of the ROS graph that act as a bus for nodes to exchange messages.

A node may publish data to any number of topics and simultaneously have subscriptions to any number of topics.

Topics are one of the main ways in which data is moved between nodes and therefore between different parts of the system.

To begin we start with a fresh new terminal ( Ctrl + Alt + T ) and type the following command:

bash
ros2 run turtlesim turtlesim_node

And of course we would like to control this turtle so we need to add the teleop node as well.

bash
ros2 run turtlesim turtle_teleop_key

Graphing the Topics Throughout this tutorial, we will use rqt_graph to visualize the changing nodes and topics, as well as the connections between them.

The turtlesim tutorial tells us how to install rqt and all its plugins, including rqt_graph.

To run rqt_graph, open a new terminal and enter the command:

bash
rqt_graph

PIC

Figure 7.2: A visual representation of the communication happening between the nodes /turtlesim and /teleop.

Wou should see the above nodes and topic, as well as two (2) actions around the periphery of the graph. If we hover your mouse over the topic in the centre, we’ll see the color highlighting.

The graph is depicting how the /turtlesim node and the /teleop_turtle node are communicating with each other over a topic. The /teleop_turtle node is publishing data 10 10 the keystrokes you enter to move the turtle around to the /turtle1/cmd_vel topic, and the /turtlesim node is subscribed to that topic to receive the data.

The highlighting feature of rqt_graph is very helpful when examining more complex systems with many nodes and topics connected in many different ways.

ros2 topic list Running the ros2 topic list command in a new terminal will return a list of all the topics currently active in the system:

bash
ros2 topic list
text
/parameter_events /rosout /turtle1/cmd_vel /turtle1/color_sensor /turtle1/pose

Alternatively, running ros2 topic list -t will return the same list of topics, this time with the topic type appended in brackets:

bash
ros2 topic list -t
text
/parameter_events [rcl_interfaces/msg/ParameterEvent] /rosout [rcl_interfaces/msg/Log] /turtle1/cmd_vel [geometry_msgs/msg/Twist] /turtle1/color_sensor [turtlesim/msg/Color] /turtle1/pose [turtlesim/msg/Pose]

These attributes, particularly the type, are how nodes know they’re talking about the same information as it moves over topics.

If you’re wondering where all these topics are in rqt_graph, you can uncheck all the boxes under Hide:

PIC

Figure 7.3:

ros2 topic echo To see the data being published on a topic, use:

bash
ros2 topic echo <topic_name>

Since we know that /teleop_turtle publishes data to /turtlesim over the /turtle1/cmd_vel topic, let’s use echo to introspect that topic:

bash
ros2 topic echo /turtle1/cmd_vel

At first, this command won’t return any data. That’s because it’s waiting for /teleop_turtle to publish something.

Return to the terminal where turtle_teleop_key is running and use the arrows to move the turtle around. Watch the terminal where your echo is running at the same time, and you’ll see position data being published for every movement you make:

text
linear: x: 2.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0 ---

Now return to rqt_graph and uncheck the Debug box.

PIC

Figure 7.4:

/_ros2cli_5707 is the node created by the echo command we just ran (the number might be different). Now you can see that the publisher is publishing data over the cmd_vel topic, and two (2) subscribers are subscribed to it.

ros2 topic info Topics don’t have to only be one-to-one communication; they can be one-to-many, many-to-one, or many-to-many.

Another way to look at this is running:

bash
ros2 topic info /turtle1/cmd_vel
text
Type: geometry_msgs/msg/Twist Publisher count: 1 Subscription count: 2

ros2 interface show Nodes send data over topics using messages. Publishers and subscribers must send and receive the same type of message to communicate.

The topic types we saw earlier after running ros2 topic list -t let us know what message type is used on each topic. Recall that the cmd_vel topic has the type:

bash
geometry_msgs/msg/Twist

This means that in the package geometry_msgs there is a msg called Twist.

Now we can run ros2 interface show <msg_type> on this type to learn its details. Specifically, what structure of data the message expects.

bash
ros2 interface show geometry_msgs/msg/Twist

Which will return

text
# This expresses velocity in free space broken into its linear and angular parts. Vector3 linear float64 x float64 y float64 z Vector3 angular float64 x float64 y float64 z

This tells you that the /turtlesim node is expecting a message with two vectors, linear and angular, of three elements each. If you recall the data we saw /teleop_turtle passing to /turtlesim with the echo command, it’s in the same structure:

text
linear: x: 2.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0 ---

7.5 Working with Services

As a brief review, services are yet another method of communication for nodes in the ROS graph. Services are based on a call-and-response model versus the publisher-subscriber model of topics. While topics allow nodes to subscribe to data streams and get continual updates, services only provide data when they are specifically called by a client.

To begin we start with a fresh new terminal ( Ctrl + Alt + T ) and type the following command to start the /turtlesim and /teleop_turtle nodes:

bash
ros2 run turtlesim turtlesim_node

bash
ros2 run turtlesim turtle_teleop_key

ros2 service list Running the ros2 service list command in a new terminal will return a list of all the services currently active in the system:

bash
ros2 service list
text
/clear /kill /reset /spawn /teleop_turtle/describe_parameters /teleop_turtle/get_parameter_types /teleop_turtle/get_parameters /teleop_turtle/list_parameters /teleop_turtle/set_parameters /teleop_turtle/set_parameters_atomically /turtle1/set_pen /turtle1/teleport_absolute /turtle1/teleport_relative /turtlesim/describe_parameters /turtlesim/get_parameter_types /turtlesim/get_parameters /turtlesim/list_parameters /turtlesim/set_parameters /turtlesim/set_parameters_atomically

Looking at this output we will see both nodes have the same six (6) services with parameters in their names. Nearly every node in ROS has these infrastructure services that parameters are built off of.

For now, let’s focus on the turtlesim-specific services:

  • /clear,

  • /kill

  • /reset

  • /spawn,

  • /turtle1/set_pen,

  • /turtle1/teleport_absolute, and

  • /turtle1/teleport_relative.

We have interacted some of these services using rqt previously.

ros2 service type Services have types which describe how the request and response data of a service is structured. Service types are defined similarly to topic types, except service types have two (2) parts:

  • one message for request,

  • another one for response.

To find out the type of a service, use the command:

bash
ros2 service type <service_name>

Let’s take a look at turtlesim’s /clear service. In a brand new terminal, let’s enter the command:

bash
ros2 service type /clear
text
std_srvs/srv/Empty

In this context, the Empty type means the service call sends no data when making a request and receives no data when receiving a response.

ros2 service list -t To see the types of all the active services at the same time, we can append the --show-types option, abbreviated as -t, to the list command:

bash
ros2 service list -t
text
/clear [std_srvs/srv/Empty] /kill [turtlesim/srv/Kill] /reset [std_srvs/srv/Empty] /spawn [turtlesim/srv/Spawn] ... /turtle1/set_pen [turtlesim/srv/SetPen] /turtle1/teleport_absolute [turtlesim/srv/TeleportAbsolute] /turtle1/teleport_relative [turtlesim/srv/TeleportRelative] ...

ros2 service find If we want to find all the services of a specific type, we can use the command, which the syntax is as follows:

bash
ros2 service find <type_name>

For example, we can find all the Empty typed services like this:

bash
ros2 service find std_srvs/srv/Empty
text
/clear /reset

ros2 interface show We can call services from the command line, but first we need to know the structure of the input arguments. The syntax of the interface command is as follows:

bash
ros2 interface show <type_name>

Try this on the /clear service’s type, Empty :

bash
ros2 interface show std_srvs/srv/Empty
text
---

The --- separates the request structure (above) from the response structure (below). But, as we learned earlier, the Empty type doesn’t send or receive any data. So, naturally, its structure is blank.

Let’s introspect a service with a type that sends and receives data, like /spawn. From the results of ros2 service list -t, we know /spawn ’s type is turtlesim/srv/Spawn.

To see the request and response arguments of the /spawn service, run the command:

bash
ros2 interface show turtlesim/srv/Spawn
text
float32 x float32 y float32 theta string name # Optional. A unique name will be created and returned if this is empty --- string name

The information above the --- line tells us the arguments needed to call /spawn. x, y and theta determine the 2D pose of the spawned turtle, and name is clearly optional.

The information below the line isn’t something we need to know in this case, but it can help us understand the data type of the response we get from the call.

ros2 service call Now that we know what a service type is, how to find a service’s type, and how to find the structure of that type’s arguments, we can call a service using:

bash
ros2 service call <service_name> <service_type> <arguments>

The <arguments> part is optional. For example, we know that Empty typed services don’t have any arguments:

bash
ros2 service call /clear std_srvs/srv/Empty

This command will clear the turtlesim window of any lines our turtle has drawn. Now let’s spawn a new turtle by calling /spawn and setting arguments. Input <arguments> in a service call from the command-line need to be in YAML syntax.

Enter the command:

bash
ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
text
requester: making request: turtlesim.srv.Spawn_Request(x=2.0, y=2.0, theta=0.2, name='') response: turtlesim.srv.Spawn_Response(name='turtle2')

We will get this method-style view of what’s happening, and then the service response.

Our turtlesim window will update with the newly spawned turtle right away:

7.6 Working with Parameters

To give a brief refreshment, a parameter is a configuration value of a node. Think of parameters as node settings or its configuration file. A node can store parameters as integers, floats, booleans, strings, and lists.

In ROS , each node maintains its own parameters.

To begin we start with a fresh new terminal ( Ctrl + Alt + T ) and type the following command:

bash
ros2 run turtlesim turtlesim_node

And of course we would like to control this turtle so we need to add the teleop node as well.

bash
ros2 run turtlesim turtle_teleop_key

ros2 param list Now that both of them are running at the same time , lets look at all the parameters in this system

bash
ros2 run turtlesim turtle_teleop_key
text
/teleop_turtle: qos_overrides./parameter_events.publisher.depth qos_overrides./parameter_events.publisher.durability qos_overrides./parameter_events.publisher.history qos_overrides./parameter_events.publisher.reliability scale_angular scale_linear use_sim_time /turtlesim: background_b background_g background_r qos_overrides./parameter_events.publisher.depth qos_overrides./parameter_events.publisher.durability qos_overrides./parameter_events.publisher.history qos_overrides./parameter_events.publisher.reliability use_sim_time

Every node has the parameter use_sim_time. It is NOT unique to turtlesim.

Based on their names, it looks like /turtlesim parameters determine the background color of the turtlesim window using RGB color values.

ros2 param get To determine a type of the parameter we are trying to understand let’s use ros2 param get. The following is the syntax of the command

bash
ros2 param get <node_name> <parameter_name>

Now, let’s use this command to determine they type and the value of the parameter:

text
Integer value is: 86

It seems the background_g parameter holds an integer value. If we were to run the same command on background_r and background_b, we will get the values 69 and 255 , respectively.

ros2 param set Time to change these parameters and play around. To change a parameter’s value at runtime, use the command:

bash
ros2 param set <node_name> <parameter_name> <value>

Let’s do something simple and try to change the /turtlesim node’s background:

bash
ros2 param set /turtlesim background_r 150
text
Set parameter successful

The background of our turtlesim window should change colours. 11 PIC 11 While the original value was 86 by using ros param set we were able to change the value of the parameter and change the background to a nice purple. It is worth mentioning that, setting parameters with the set command will only change them in our current session, NOT permanently. However, we can save our settings and reload them the next time we want to start a node.

ros2 param dump For this we need to dump this parameters to some other file for later use. Let’s have a look at the ros2 param dump command. This allows us to view all of a node’s current parameter values:

bash
ros2 param dump <node_name>

The command prints to the standard output (stdout) by default but we can also redirect the parameter values into a file to save them for later.

To save our current configuration of /turtlesim parameters into the file turtlesim.yaml, enter the command:

bash
ros2 param dump /turtlesim > turtlesim.yaml

In the current working directory we will find a new file. If we were to open this file, we’ll see the following content:

yaml
/turtlesim: ros__parameters: background_b: 255 background_g: 86 background_r: 150 qos_overrides: /parameter_events: publisher: depth: 1000 durability: volatile history: keep_last reliability: reliable use_sim_time: false

Dumping parameters comes in handy if we want to reload the node with the same parameters in the future.

ros2 param load Once the parameters are dumped into a file, we can load them to a currently running node using the command:

bash
ros2 param load <node_name> <parameter_file>

To load the turtlesim.yaml file we just generated with ros2 param dump into /turtlesim node parameters, we just have to enter the command:

bash
ros2 param load /turtlesim turtlesim.yaml
text
Set parameter background_b successful Set parameter background_g successful Set parameter background_r successful Set parameter qos_overrides./parameter_events.publisher.depth failed: parameter 'qos_overrides./parameter_events.publisher.depth' cannot be set because it is read-only Set parameter qos_overrides./parameter_events.publisher.durability failed: parameter 'qos_overrides./parameter_events.publisher.durability' cannot be set because it is read-only Set parameter qos_overrides./parameter_events.publisher.history failed: parameter 'qos_overrides./parameter_events.publisher.history' cannot be set because it is read-only Set parameter qos_overrides./parameter_events.publisher.reliability failed: parameter 'qos_overrides./parameter_events.publisher.reliability' cannot be set because it is read-only Set parameter use_sim_time successful

Read-only parameters can only be modified at startup and not afterwards, that is why there are some warnings for the qos_overrides parameters.

Loading Parameters on Startup To start the same node using our saved parameter values, use:

bash
ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>

This is the same command we always use to start turtlesim, with the added flags --ros-args and --params-file, followed by the file we want to load.

To test this out, stop our running turtlesim node, and try reloading it with our saved parameters, using:

bash
ros2 run turtlesim turtlesim_node --ros-args --params-file turtlesim.yaml

The turtlesim window should appear as usual, but with the purple background we set earlier.

When a parameter file is used at node startup, all parameters, including the read-only ones, will be updated.

7.7 A Practical Look into Actions

Actions are one of the communication types in ROS and are intended for long running tasks. They consist of three parts: a goal, feedback, and a result.

Actions are built on topics and services. Their functionality is similar to services, except actions can be canceled. They also provide steady feedback, as opposed to services which return a single response.

Actions use a client-server model, similar to the publisher-subscriber model (described in the topics tutorial). An “action client” node sends a goal to an “action server” node that acknowledges the goal and returns a stream of feedback and a result.

To begin we start with a fresh new terminal ( Ctrl + Alt + T ) and type the following command:

bash
ros2 run turtlesim turtlesim_node

And of course we would like to control this turtle so we need to add the teleop node as well.

bash
ros2 run turtlesim turtle_teleop_key

When we launch the /teleop_turtle node, we will see the following message in our terminal:

text
Use arrow keys to move the turtle. Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.

Let’s focus on the second line, which corresponds to an action. Pay attention to the terminal where the /turtlesim node is running. Each time we press one of these keys, we are sending a goal to an action server that is part of the /turtlesim node. The goal is to rotate the turtle to face a particular direction. A message relaying the result of the goal should display once the turtle completes its rotation:

text
[INFO] [turtlesim]: Rotation goal completed successfully

The F key will cancel a goal mid-execution.

Try pressing the C key, and then pressing the F key before the turtle can complete its rotation. In the terminal where the /turtlesim node is running, we will see the message:

text
[INFO] [turtlesim]: Rotation goal canceled

Not only can the client-side (our input in the teleop) stop a goal, but the server-side (the /turtlesim node) can as well. When the server-side chooses to stop processing a goal, it is said to “abort” the goal.

Try hitting the D key, then the G key before the first rotation can complete. In the terminal where the /turtlesim node is running, we will see the message:

text
[WARN] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goal

This action server chose to abort the first goal because it got a new one. It could have chosen something else, like reject the new goal or execute the second goal after the first one finished. Don’t assume every action server will choose to abort the current goal when it gets a new one.

ros2 node info To see the list of actions a node provides, /turtlesim in this case, open a new terminal and run the command:

bash
ros2 node info /turtlesim
text
/turtlesim Subscribers: /parameter_events: rcl_interfaces/msg/ParameterEvent /turtle1/cmd_vel: geometry_msgs/msg/Twist Publishers: /parameter_events: rcl_interfaces/msg/ParameterEvent /rosout: rcl_interfaces/msg/Log /turtle1/color_sensor: turtlesim/msg/Color /turtle1/pose: turtlesim/msg/Pose Service Servers: /clear: std_srvs/srv/Empty /kill: turtlesim/srv/Kill /reset: std_srvs/srv/Empty /spawn: turtlesim/srv/Spawn /turtle1/set_pen: turtlesim/srv/SetPen /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute /turtle1/teleport_relative: turtlesim/srv/TeleportRelative /turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters /turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes /turtlesim/get_parameters: rcl_interfaces/srv/GetParameters /turtlesim/list_parameters: rcl_interfaces/srv/ListParameters /turtlesim/set_parameters: rcl_interfaces/srv/SetParameters /turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically Service Clients: Action Servers: /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute Action Clients:

The command returns a list of /turtlesim’s subscribers, publishers, services, action servers and action clients.

Notice that the /turtle1/rotate_absolute action for /turtlesim is under Action Servers. This means /turtlesim responds to and provides feedback for the /turtle1/rotate_absolute action.

The /teleop_turtle node has the name /turtle1/rotate_absolute under Action Clients meaning that it sends goals for that action name. To see that, run:

bash
ros2 node info /teleop_turtle
text
/teleop_turtle Subscribers: /parameter_events: rcl_interfaces/msg/ParameterEvent Publishers: /parameter_events: rcl_interfaces/msg/ParameterEvent /rosout: rcl_interfaces/msg/Log /turtle1/cmd_vel: geometry_msgs/msg/Twist Service Servers: /teleop_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters /teleop_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes /teleop_turtle/get_parameters: rcl_interfaces/srv/GetParameters /teleop_turtle/list_parameters: rcl_interfaces/srv/ListParameters /teleop_turtle/set_parameters: rcl_interfaces/srv/SetParameters /teleop_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically Service Clients: Action Servers: Action Clients: /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute

ros2 action list To identify all the actions in the ROS graph, run the command:

bash
ros2 action list
text
/turtle1/rotate_absolute

This is the only action in the ROS graph right now. It controls the turtle’s rotation, as we saw earlier. We also already know that there is one action client (part of /teleop_turtle ) and one action server (part of /turtlesim ) for this action from using the ros2 node info <node_name> command.

ros2 action list -t Actions have types, similar to topics and services. To find /turtle1/rotate_absolute ’s type, run the command:

bash
ros2 action list -t
text
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]

In brackets to the right of each action name (in this case only /turtle1/rotate_absolute ) is the action type, turtlesim/action/RotateAbsolute. We will need this when we want to execute an action from the command line or from code.

7.8 Launching Nodes

Up to now, we have been opening new terminals for every new node we ran. As we create more complex systems with more and more nodes running simultaneously, opening terminals and reentering configuration details becomes tedious.

Launch files allow we to start up and configure a number of executables containing ROS nodes simultaneously.

Running a single launch file with the ros2 launch command will start up our entire system 12 12 which includes all nodes and their configurations at once.

bash
ros2 launch turtlesim multisim.launch.py

This command will run the following launch file:

python
from launch import LaunchDescription import launch_ros.actions def generate_launch_description(): return LaunchDescription([ launch_ros.actions.Node( namespace='turtlesim1', package='turtlesim', executable='turtlesim_node', output='screen'), launch_ros.actions.Node( namespace='turtlesim2', package='turtlesim', executable='turtlesim_node', output='screen'), ])

The launch file above is written in Python, but we can also use XML and YAML to create launch files. We can see a comparison of these different ROS launch formats in Using XML, YAML, and Python for ROS Launch Files.

If this is working well, then we should see two turtlesim environments popping up. This will run two (2) turtlesim nodes.

Controlling the Nodes Now that these nodes are running, we can control them like any other ROS nodes. For example, we can make the turtles drive in opposite directions by opening up two additional terminals and running the following commands:

In a second terminal:

bash
ros2 topic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"

In a third terminal:

bash
ros2 topic pub /turtlesim2/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}"

After running these commands, we should see the two turtles in their respective envrionment spinning like a record.