The ROS Command Line Interface
The ROS command line interface, or CLI for short, is a set of programs for starting, inspecting, controlling, and monitoring a ROS robot. The best way to think of the CLI is a collection of small and simple programs that allow you perform basic tasks in ROS. Drawing from our car analogy, the CLI can be thought of as the subsystems of a vehicle: the breaks, the transmission, the window wipers, all of the smaller parts that are composed together to build the larger vehicle. What we'll show you in this section is how to turn on the car, put it in gear, turn on the radio, and perhaps check your oil to perform routine maintenance. The ROS 2 CLI draws heavily from the Unix/Linux philosophy of small programs that can be composed together. If you are familiar with the command line interface found in Unix and Linux, or to a lesser extent in MacOS or Windows, you'll feel right at home.
The ROS command line tools draw heavily from the design patterns mentioned in the previous section, and directly interface with the APIs we will address in the next section. The CLI interface is at its core just a set of simple tools built from the ROS 2 API; this API is simply an implementation of the high-level patterns we discussed in the previous section. If your goal is to simply interface with a particular piece of software written using ROS, the CLI interface is the way you will go about starting, stopping, and controlling the underlying ROS software. For more advanced users these tools will allow you to study a ROS system by exploring the underlying software processes in the system.
There are only two things you need to memorize from this section. The first command simply tells your computer that you are using ROS, and what version of ROS you want to use. Let's take a look at the magic command:
source /opt/ros/eloquent/setup.bash
If everything is working correctly, this command should simply return. Nothing happens that you can see, but underneath the hood you've just told this particular shell that you are using ROS 2 Eloquent Elusor, and where all the ROS programs and files live. You should plan on doing this every time you want to use ROS. The most common mistake new users have is not running this command. If you're not sure if you ran the command in a shell, that's okay. The command is idempotent; running it twice in a row won't break anything. You can run it a million times in a row and it won't make any difference.
The other command you need to commit to memory is ros2
. Almost everything in
the ROS 2 CLI starts with ros2
. Go ahead and try it in the same shell where you just sourced the setup file.
If everything is working correctly you should see the following:
$ ros2
usage: ros2 [-h] Call `ros2 <command> -h` for more detailed usage. ...
ros2 is an extensible command-line tool for ROS 2.
optional arguments:
-h, --help show this help message and exit
Commands:
action Various action related sub-commands
component Various component related sub-commands
daemon Various daemon related sub-commands
doctor Check ROS setup and other potential issues
interface Show information about ROS interfaces
launch Run a launch file
lifecycle Various lifecycle related sub-commands
msg Various msg related sub-commands
multicast Various multicast related sub-commands
node Various node related sub-commands
param Various param related sub-commands
pkg Various package related sub-commands
run Run a package specific executable
security Various security related sub-commands
service Various service related sub-commands
srv Various srv related sub-commands
topic Various topic related sub-commands
wtf Use `wtf` as alias to `doctor`
Call `ros2 <command> -h` for more detailed usage.
From this one command you can figure out what every single ROS 2 CLI program does and
how to use it. The ROS 2 CLI has a syntax just like most languages. All ROS CLI commands start
with ros2
, followed by a command. After the command any number of other things
can come; you can append --help
or -h
to see the documentation and find out what arguments any of the commands are expecting.
The rest of this section just walks through each of the commands one by one.
Writing commands using the command line is tricky and error
prone. There are a couple of tools you can use to make the process much
smoother. The first is the TAB
key, which attempts to auto complete whatever you type.
It can't read your mind, but for common command combinations you usually only need to type the
first one or two letters. Another tool is the up arrow key. When you use the
command line sometimes you mistype a command, or need to rerun a
command. Pressing the up key will cycle through the previous commands which you
can modify and rerun as needed.
Running Your First ROS Program
Let's get started with our first ROS CLI command. The first command we'll visit
is run
. Let's start by looking at the documentation for the run
command:
$ ros2 run
usage: ros2 run [-h] [--prefix PREFIX] package_name executable_name ...
ros2 run: error: the following arguments are required: package_name, executable_name, argv
To get more complete information about a ROS 2 command, simply ask the command for help by
adding --help
to the command. Let's try that again:
$ ros2 run --help
usage: ros2 run [-h] [--prefix PREFIX] package_name executable_name ...
Run a package specific executable
positional arguments:
package_name Name of the ROS package
executable_name Name of the executable
argv Pass arbitrary arguments to the executable
optional arguments:
-h, --help show this help message and exit
--prefix PREFIX Prefix command, which should go before the executable.
Command must be wrapped in quotes if it contains spaces
(e.g. --prefix 'gdb -ex run --args').
We can see that ros2 run
is the
command to, "Run a package specific executable." In ROS 2 collections of ROS
software are gathered into logical units called packages
. Each package
contains all of the source code for the package as a variety of other data that
tells ROS how to build and compile the package and the names of all the
programs, also called executables
, that can be found in the package. The line
below the description then gives the positional arguments for the
package. Positional arguments are the words and values that come after ros2
and the command you run. In this case the syntax for the command sentence we
want to write is as follows:
ros2 run <package name> <program/executable name> <args>
There is one piece of missing information here. What is this argv
that the
command is asking for? The argv
element is programmer short hand for variable
arguments, and it simply means, "some number of additional arguments that are
determined by the executable". It is worth noting that a program can have zero
arguments and you can just leave it blank. This is actually how a lot of
programs work. For example, say we had a package
called math, and an executable called add that takes in two numbers and
returns the result. In this case argv would be the two numbers to add. The
final command would look like:
ros2 run math add 1 2
Finally, below the positional arguments we have optional arguments. You don't need to included them, unless you need to.
Now that we've looked into our help file let's run our first ROS program. For
these tutorials we're going to use a package called turtlesim
, and the program
we want to run is turtlesim_node
. Let's run this program (remember your tab
complete!). Your command should look like the following:
ros2 run turtlesim turtlesim_node
If everything goes smoothly you should see the following:
[INFO] [turtlesim]: Starting turtlesim with node name /turtlesim
[INFO] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]
A window should also pop up with a cute little turtle that looks like the one below:
The real power in ROS isn't that it can run a program, it is that it can run lots of programs all at the same time, all talking together to control a robot, or multiple robots, all working together. To illustrate this let's run a second ROS program that makes our little turtle move around.
To do this we'll first open a new terminal (using CTRL-SHIFT-T
). Next we'll
tell that terminal that we want to use ROS Eloquent by using the source
command.
Finally, we'll run another program in the
turtlesim
package to draw a square. See if you can find the program
yourself (hint: use TAB
). If everything works you should have typed the following, and the
following output should be visible:
$ source /opt/ros/eloquent/setup.bash
$ ros2 run turtlesim draw_square
[INFO] [draw_square]: New goal [7.544445 5.544445, 0.000000]
[INFO] [draw_square]: Reached goal
[INFO] [draw_square]: New goal [7.448444 5.544445, 1.570796]
[INFO] [draw_square]: Reached goal
Your screen should look roughly like this:
It is worth noting that you can stop any ROS program by pressing the Ctrl
and
C
keys at the same time in the terminal; we call this CTRL-C
(note that
CTRL-SHIFT-C
and CTRL-SHIFT-V
are responsible for copy and paste in a Linux terminal).
Feel free to try it out. Start and stop the programs, and then
restart them before moving on.
ROS Topics
We now have two ROS 2 programs running from the turtlesim
package.
There is turtle_node
that opens our turtle simulation, and draw_square
that makes the turtle in turtle_node
move around. How are these two
programs communicating?
ROS programs, also called nodes, communicate over topics on the ROS message bus. ROS topics use namespaces to distinguish themselves. For example, in a vehicle running ROS, the positions of each wheel may be organized as follows:
/wheels/front/driver/velocity
/wheels/front/passenger/velocity
/wheels/rear/driver/velocity
/wheels/rear/passenger/velocity
The key thing to realize about topics is that the data they contain is dynamic, meaning it changes
constantly. In our vehicle example the velocity of each wheel might be measured
one thousand times a second or more. Since the data in a ROS topic is constantly
changing, an important distinction for a topic is whether the topic is "creating"
or as we like to say in ROS publishing
, or if it is reading the data, what we call
subscribing
to the topic. Many ROS nodes subscribe to one set of topics,
process that input data, and then publish to another set of topics.
Let's return to our turtlesim example and see if we can use the ROS CLI to
understand the topics, publishers, and subscribers.
To see sub commands and syntax for the topic
command, we'll run: ros2 topic --help
.
This command outputs the following:
$ ros2 topic --help
usage: ros2 topic [-h] [--include-hidden-topics]
Call `ros2 topic <command> -h` for more detailed usage. ...
Various topic related sub-commands
optional arguments:
-h, --help show this help message and exit
--include-hidden-topics
Consider hidden topics as well
Commands:
bw Display bandwidth used by topic
delay Display delay of topic from timestamp in header
echo Output messages from a topic
find Output a list of available topics of a given type
hz Print the average publishing rate to screen
info Print information about a topic
list Output a list of available topics
pub Publish a message to a topic
type Print a topic's type
Call `ros2 topic <command> -h` for more detailed usage.
There are quite a
few sub commands; we won't discuss all of them, but let's look closely at a few.
Sub commands have their
own help command. Why don't we examine the list
command. Repeating our command
pattern let's try running ros2 topic list --help
.
usage: ros2 topic list [-h] [--spin-time SPIN_TIME] [-t] [-c]
[--include-hidden-topics]
Output a list of available topics
optional arguments:
-h, --help show this help message and exit
--spin-time SPIN_TIME
Spin time in seconds to wait for discovery (only
applies when not using an already running daemon)
-t, --show-types Additionally show the topic type
-c, --count-topics Only display the number of topics discovered
--include-hidden-topics
Consider hidden topics as well
As indicated at the top of this command help file, ros2 topic list
will
"Output a list of available topics." There appears to be a variety of
optional arguments that we don't need to include if we don't want to. However,
the -t, --show-types
line looks interesting. It is worth noting that command
arguments, sometimes called flags, can have two types. A short form indicated
with a single dash ("-"), and a long form indicated by a double dash
("--"). Don't worry, despite looking different both versions of the argument do
the same thing. Let's try running this command, sub command pair with the
-show-types
argument.
$ ros2 topic list --show-types
/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]
On the left hand side we see all of the ROS topics
running on the system, each starting with /
. We can see that most of them are gathered in the
/turtle1/
group. This group defines all the inputs and outputs of the little
turtle on our screen. The words in brackets ([]
) to the right of the topic
names define the messages used on the topic. Our car wheel example was
simple, we were only publishing velocity, but ROS allows you to publish more
complex data structures that are defined by a message type. When we added the
--show-types
flag we told the command to include this information. We'll dig
into messages in detail a bit later.
One of the more commonly used topic sub commands is
info
. Unsurprisingly, info
provides info about a topic. Let's peek at its
help file using ros2 topic info --help
$ ros2 topic info --help
usage: ros2 topic info [-h] topic_name
Print information about a topic
positional arguments:
topic_name Name of the ROS topic to get info (e.g. '/chatter')
optional arguments:
-h, --help show this help message and exit
That seems pretty straight forward. Let's give it a go by running it on
/turtle1/pose
$ ros2 topic info /turtle1/pose
Type: turtlesim/msg/Pose
Publisher count: 1
Subscriber count: 1
What does this command tell us? First it tells us the message type for the
/turtle1/pose
topic, which is /turtlesim/msg/Pose
. From this we can determine that the
message type comes from the turtlesim package, and its type is Pose
. ROS
messages have a predefined message type that can be shared by different
programming languages and between different nodes. We can also see that this
topic has a single publisher, that is to say a single node generating data on the
topic. The topic also has a single subscriber, also called a listener, who is
processing the incoming pose data.
If we only wanted to know the message type of a topic
there is a sub command just for that called, type
. Let's take a look at its
help file and its result:
$ ros2 topic type --help
usage: ros2 topic type [-h] topic_name
Print a topic's type
positional arguments:
topic_name Name of the ROS topic to get type (e.g. '/chatter')
optional arguments:
-h, --help show this help message and exit
kscottz@kscottz-ratnest:~/Code/ros2multirobotbook$ ros2 topic type /turtle1/pose
turtlesim/msg/Pose
While it is not part of the topic
command it is worthwhile for us to jump ahead
briefly and look at one particular command, sub command pair, namely the interface
command and the show
sub command. This sub command will print all the
information related to a message type so you can better understand the data
being moved over a topic. In the previous example we saw that the topic type
sub command told us the /turtle1/pose
topic has a type turtlesim/msg/Pose
.
But what does turtlesim/msg/Pose
data look like? We can look at the data
structure transferred by this topic by running the ros2 interface show
sub command and giving the message type name as an input. Let's look at the help
for this sub command and its output:
$ ros2 interface show --help
usage: ros2 interface show [-h] type
Output the interface definition
positional arguments:
type Show an interface definition (e.g. "std_msgs/msg/String")
optional arguments:
-h, --help show this help message and exit
$ ros2 interface show turtlesim/msg/Pose
float32 x
float32 y
float32 theta
float32 linear_velocity
float32 angular_velocity
We can see the values x
and y
which are the position coordinates of our turtle,
and that they are of type float32
.
theta
is the direction the head is pointing. The
next two values, linear_velocity
and angular_velocity
, are how
fast the turtle is moving and how quickly it is turning, respectively. To summarize, this
message tells us where a turtle is on the screen, where it is headed, and how
fast it is moving or rotating.
Now that we know what ROS topics are on our simple turtlesim, and their message
types, we can dig in and find out more about how everything works. If we look
back at our topic sub commands, we can see a sub command called echo
. Echo is
computer jargon that means "repeat" something. If you echo a topic it means you
want the CLI to repeat what's on a topic. Let's look at the echo
sub command's
help text:
$ ros2 topic echo --help
usage: ros2 topic echo [-h]
[--qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}]
[--qos-reliability {system_default,reliable,best_effort}]
[--qos-durability {system_default,transient_local,volatile}]
[--csv] [--full-length]
[--truncate-length TRUNCATE_LENGTH] [--no-arr]
[--no-str]
topic_name [message_type]
Output messages from a topic
positional arguments:
topic_name Name of the ROS topic to listen to (e.g. '/chatter')
message_type Type of the ROS message (e.g. 'std_msgs/String')
optional arguments:
-h, --help show this help message and exit
--qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}
Quality of service preset profile to subscribe with
(default: sensor_data)
--qos-reliability {system_default,reliable,best_effort}
Quality of service reliability setting to subscribe
with (overrides reliability value of --qos-profile
option, default: best_effort)
--qos-durability {system_default,transient_local,volatile}
Quality of service durability setting to subscribe
with (overrides durability value of --qos-profile
option, default: volatile)
--csv Output all recursive fields separated by commas (e.g.
for plotting)
--full-length, -f Output all elements for arrays, bytes, and string with
a length > '--truncate-length', by default they are
truncated after '--truncate-length' elements with
'...''
--truncate-length TRUNCATE_LENGTH, -l TRUNCATE_LENGTH
The length to truncate arrays, bytes, and string to
(default: 128)
--no-arr Don't print array fields of messages
--no-str Don't print string fields of messages
Wow, that's a lot of features. The top of the help files says that this CLI
program "output[s] messages from a topic." As we scan the positional arguments we see one
required argument, a topic name, and an optional message type. We know the
message type is optional because it has square brackets ([]
) around it. Let's
give the simple case a whirl before we address some of the optional
elements. Two things to keep in mind: first is that topics are long and easy to mess
up, so use the TAB
key. Second is that this will print a lot of data, fast. You can
use CTRL-C
to stop the command and stop all the output. Let's take a look at the
/turtle1/pose
topic.
$ ros2 topic echo /turtle1/pose
x: 5.4078755378723145
y: 7.081490516662598
theta: -1.0670461654663086
linear_velocity: 1.0
angular_velocity: 0.0
---
x: 5.4155988693237305
y: 7.067478179931641
theta: -1.0670461654663086
linear_velocity: 1.0
angular_velocity: 0.0
---
x: 5.423322677612305
y: 7.053465843200684
theta: -1.0670461654663086
linear_velocity: 1.0
angular_velocity: 0.0
---
<<GOING ON FOREVER>>
Let's examine what is going on. Between the
dashes (---
) is a single ROS message on our topic. If you examine the numbers
closely you can see that they are changing, and doing so in relation to the
movement of the turtle. Going back to our car example you can see how this would
be useful for understanding the instantaneous velocity of each of our wheels.
Now that we have the basics down let's dig into a few of the optional
arguments. We see a variety of commands that start with --qos
. "QOS" here
means "quality of service" and it is a really cool feature that is only in
ROS 2. Without getting too technical, QOS is a way of asking for a certain level
of networking robustness. A ROS system can operate over a network, and just like
streaming video or video games, packets can get dropped or not get to their
destination. The OS settings help you control which packets are the most
important and should get the highest priority.
Most of the other commands deal with changing the output format of this CLI
program, but there is one in particular that is super handy, and it is also new
in ROS 2. The --csv
flag stands for "comma separated values" and it a very
simple way of defining a spreadsheet. What this argument does is make the topic
echo command output data in the comma separate value format. Many command lines
allow you send data from the screen to a file, saving the data for later
review or analysis. To do this file saving in Linux we use the >
character
followed by a file name. Below are two examples of using the --csv
argument:
$ ros2 topic echo /turtle1/pose --csv
7.097168922424316,8.498645782470703,2.442624092102051,0.0,0.4000000059604645
7.097168922424316,8.498645782470703,2.449024200439453,0.0,0.4000000059604645
...
<<CTRL-C>>
$ ros2 topic echo /turtle1/pose --csv > mydata.csv
<<nothing happens>>
<<CTRL-C>>
The second command above creates a file called mydata.csv
. You can look at it
using a CLI utility called less
(press q to quit), or open it with your
favorite spreadsheet tool.
Now that we've looked at ros2 topic echo
let's take a look at a few other
topic sub commands. One thing you may have noticed is that topics can output a lot
of data! More complex robots, like a self driving car, can saturate a high
speed internet connection with how much data it produces. There are two topic
sub commands that can be used to diagnose performance issues. The first
sub command is topic hz
which is the abbreviation of Hertz, the unit of
frequency. The Hz
sub command will
tell you how often a particular topic produces a message. Similarly there is
the topic bw
sub command, where bw
stands for bandwidth, which is a
engineering term related to the volume of data being produced. A high
bandwidth connection can move more data, like high definition video, than a low
bandwidth data, which might move a radio show. Let's take a look at the help
for these two commands:
$ ros2 topic hz --help
usage: ros2 topic hz [-h] [--window WINDOW] [--filter EXPR] [--wall-time]
topic_name
Print the average publishing rate to screen
positional arguments:
topic_name Name of the ROS topic to listen to (e.g. '/chatter')
optional arguments:
-h, --help show this help message and exit
--window WINDOW, -w WINDOW
window size, in # of messages, for calculating rate
(default: 10000)
--filter EXPR only measure messages matching the specified Python
expression
--wall-time calculates rate using wall time which can be helpful
when clock is not published during simulation
$ ros2 topic bw --help
usage: ros2 topic bw [-h] [--window WINDOW] topic
Display bandwidth used by topic
positional arguments:
topic Topic name to monitor for bandwidth utilization
optional arguments:
-h, --help show this help message and exit
--window WINDOW, -w WINDOW
window size, in # of messages, for calculating rate
(default: 100)
Both bw
and hz
follow the same pattern, they simply take in a topic name
followed by a few optional arguments. The only argument worth noting is the
window
argument. Both of these commands calculate statistics for a series of
messages; how many messages to use in calculating those statistics is the window
size. The default value for window
is 100, so when you call ros2 topic bw
it
will first collect 100 messages then use that data to calculate the average
message size. Let's give it a shot (use TAB
to complete and CTRL-C
to exit).
$ ros2 topic hz /turtle1/pose
average rate: 60.021
min: 0.001s max: 0.073s std dev: 0.00731s window: 65
average rate: 61.235
min: 0.001s max: 0.073s std dev: 0.00523s window: 128
$ ros2 topic bw /turtle1/pose
Subscribed to [/turtle1/pose]
average: 1.44KB/s
mean: 0.02KB/s min: 0.02KB/s max: 0.02KB/s window: 46
average: 1.52KB/s
mean: 0.02KB/s min: 0.02KB/s max: 0.02KB/s window: 100
As we can see above, the hz
command says that the topic is publishing messages
at 60.021, where the unit is hz, or 60.021 times a second. Notice that the
command gives the publishing frequency as an average, followed by the minimum,
maximum, and standard deviation, in seconds. The bandwidth sub command is very
similar; and we can see that the topic is producing 1.44 kilobytes of data per
second. This command has similar outputs around the minimum, maximum, and mean.
One tool that is handy when exploring topics is understanding their type. While
we have already looked at the interface
command to see what integral types make up
a topic, the topic
command has both a tool to query the type of a topic, and a
means to search all topics for a specific type. If all you want to know is a
topic's type you can use the type
command which will return a type that can
then be further explored with the interface
command. If instead you would like
to know what topics use a particular message type you can use the topic find
command, sub command pair. Both the topic type
and topic interface
command,
sub command pairs have a very limited set of optional arguments, so we simply
provide them with our desired topic or message type. Let's take a look at these two commands together:
$ ros2 topic type --help
usage: ros2 topic type [-h] topic_name
Print a topic's type
positional arguments:
topic_name Name of the ROS topic to get type (e.g. '/chatter')
optional arguments:
-h, --help show this help message and exit
$ ros2 topic type /turtle1/pose
turtlesim/msg/Pose
$ ros2 topic find --help
usage: ros2 topic find [-h] [-c] [--include-hidden-topics] topic_type
Output a list of available topics of a given type
positional arguments:
topic_type Name of the ROS topic type to filter for (e.g.
'std_msg/msg/String')
optional arguments:
-h, --help show this help message and exit
-c, --count-topics Only display the number of topics discovered
--include-hidden-topics
Consider hidden topics as wel
$ ros2 topic find turtlesim/msg/Pose
/turtle1/pose
The last sub command for the topic command is pub
, which simply means publish.
It allows you to publish a command to any ROS topic from the command
line. While you shouldn't need to use this command regularly it can be
particularly handy for testing and debugging when you are building a robot
system. The pub
command has a number of optional arguments that allow you to
send one or more messages, and with different quality of service (QoS)
presets. The format of the command is ros2 topic pub TOPIC_NAME MESSAGE_TYPE VALUES
, which means for it to work successfully you must include a
target topic, the topic's message type, and finally the message's values. The
values for the message are specified in the YAML format and we can use the
interface show
command to understand the format. To illustrate the utility of this
command we'll issue a message to rotate and stop our turtle by publishing
to the /turtle1/cmd_vel/
topic. Let's first take a look at the topic pub
documentation before we construct our command:
$ ros2 topic pub --help
usage: ros2 topic pub [-h] [-r N] [-p N] [-1] [-n NODE_NAME]
[--qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}]
[--qos-reliability {system_default,reliable,best_effort}]
[--qos-durability {system_default,transient_local,volatile}]
topic_name message_type [values]
Publish a message to a topic
positional arguments:
topic_name Name of the ROS topic to publish to (e.g. '/chatter')
message_type Type of the ROS message (e.g. 'std_msgs/String')
values Values to fill the message with in YAML format (e.g.
"data: Hello World"), otherwise the message will be
published with default values
optional arguments:
-h, --help show this help message and exit
-r N, --rate N Publishing rate in Hz (default: 1)
-p N, --print N Only print every N-th published message (default: 1)
-1, --once Publish one message and exit
-n NODE_NAME, --node-name NODE_NAME
Name of the created publishing node
--qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}
Quality of service preset profile to publish with
(default: system_default)
--qos-reliability {system_default,reliable,best_effort}
Quality of service reliability setting to publish with
(overrides reliability value of --qos-profile option,
default: system_default)
--qos-durability {system_default,transient_local,volatile}
Quality of service durability setting to publish with
(overrides durability value of --qos-profile option,
default: system_default)
Since we want to manually move our turtle we will use the --once
flag to issue our command once. It is worth noting that the message type used to
command the velocity of the turtle is complex in that it is made up of other
message types so we'll have to query the base message type. Here's a rough summary of what we will do:
- Print the
cmd_vel
topic type usingros2 topic type
, which isgeometry_msgs/msg/Twist
- Determine the structure of the
Twist
message type usinginterface show
. - Determine the structure of the
Vector3
, which is part of theTwist
message type usinginteface show
command a second time. - Create the YAML syntax for our command. Note the YAML syntax below as it is
rather tricky! The YAML is wrapped in single quotes and a top level set of
curly braces, while subsequent levels follow the
pattern of
name:value
, andname:{name1:val1,name2:val2}
for nested types like theTwist
command. - Issue the command using
ros2 pub
.
$ ros2 topic type /turtle1/cmd_vel
geometry_msgs/msg/Twist
$ ros2 interface show geometry_msgs/msg/Twist
# This expresses velocity in free space broken into its linear and angular parts.
Vector3 linear
Vector3 angular
$ ros2 interface show geometry_msgs/msg/Vector3
# This represents a vector in free space.
float64 x
float64 y
float64 z
$ ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist '{linear: {x: 4.0,y: 4.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}'
If you did everything correctly you should have moved around the turtle on the screen. Try changing the command to draw a small picture.
ROS 2 Services and Actions
As discussed previously, services are the name given to short, synchronous robot behaviors that can be done quickly, like turning on lights and switching components on or off. Actions are longer term, asynchronous, tasks that may have intermediate steps. A classic example of an action is navigation: a robot is provided a goal position and asked to navigate to that goal. Try as the robot might, since it cannot move infinitely fast, it takes time to move to a goal and sometimes its path may become blocked.
These two primitives are the backbone of most robotic systems using ROS, and learning
how to use them via the command line will allow you quickly and easily command
a robot to complete a task for you. To aid in clarity of this section we'll
also touch on the ros2 node
command to determine what node, or software
process, is conducting a particular action or service.
Let's get nodes out of the way quickly. ROS nodes are
small programs, running in their own process. A ROS system can have ten,
hundreds, or even thousands of nodes running concurrently. Moreover, a ROS
system can have multiple copies of the same node running concurrently on the
same system. In the case of our turtle simulation we can actually create
multiple turtles, each with their own node, all running the exact same
program. ROS Nodes, like ROS topics, have namespaces so that you can address
specific nodes in the case where multiple copies of the same node (program) are
running. Let's dig in a bit by restarting our turtle simulation in a terminal
using ros2 run turtlesim turtlesim_node
. Now in a new terminal let's first
examine what ros2 node
has to offer by asking for help.
$ ros2 node --help
usage: ros2 node [-h]
Call `ros2 node <command> -h` for more detailed usage. ...
Various node related sub-commands
optional arguments:
-h, --help show this help message and exit
Commands:
info Output information about a node
list Output a list of available nodes
Call `ros2 node <command> -h` for more detailed usage.
Much like topics, we see two sub commands, info
and list
. node list
works much the
same as topic list
and simply prints a list of all running nodes. Let's see what
is running on our system:
$ ros2 node list
/turtlesim
We have a single node running called "turtlesim". node info
works in a way
very similar to topic info
except that it lists information about the nodes we
give it. Let's call it with our single ROS Node /turtlesim
as its
argument:
$ ros2 node info /turtlesim
/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:
Wow, that's a lot of information, some of which looks familiar. We can see all the topics that the node subscribes to, as well as all the nodes it publishes to. We can also see a number of "action servers" and "service servers". It is worth noting the client and server relationship here. Since ROS may have multiple nodes running some nodes may offer services (these are servers), and other ROS nodes may call those servers (these are the clients). The clients can be other ROS nodes, or for these examples, a human using the CLI.
The command line interface for services and actions are very similar, in fact
they both have only four sub commands. Let's run the action
and service
commands and compare them:
$ ros2 action --help
usage: ros2 action [-h]
Call `ros2 action <command> -h` for more detailed usage.
...
Various action related sub-commands
optional arguments:
-h, --help show this help message and exit
Commands:
info Print information about an action
list Output a list of action names
send_goal Send an action goal
show Output the action definition
Call `ros2 action <command> -h` for more detailed usage.
$ ros2 service --help
usage: ros2 service [-h] [--include-hidden-services]
Call `ros2 service <command> -h` for more detailed usage.
...
Various service related sub-commands
optional arguments:
-h, --help show this help message and exit
--include-hidden-services
Consider hidden services as well
Commands:
call Call a service
find Output a list of available services of a given type
list Output a list of available services
type Output a service's type
Call `ros2 service <command> -h` for more detailed usage.
We can see that both commands have a list
command that gives a list of
available services or actions. If we had multiple nodes running and wanted to
see every service offered, calling ros2 node info
on each node would be very
inefficient, particularly if we had tens, or even hundreds of nodes running.
In this case it would be much more efficient to use the list commands for the
action and service commands. We can run these commands below and see that we get
roughly the same list of actions and services listed in our single nodes:
$ ros2 service list
/clear
/kill
/reset
/spawn
/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
kscottz@kscottz-ratnest:~$ ros2 action list
/turtle1/rotate_absolute
Let's begin digging into services. There seem to be quite a few services
listed. Let's take a look at the /spawn
service, which will create more
turtles. ROS services and actions use messages similar to those used in topics
to communicate. In fact, actions and services are built on top of messages.
We can use the service type
sub command to determine the message type
used by a particular service. We can find specifics of the message by using the
interface show
command. Let's see this in practice with the spawn
service:
$ ros2 service type /spawn
turtlesim/srv/Spawn
$ ros2 interface show turtlesim/srv/Spawn
float32 x
float32 y
float32 theta
string name # Optional. A unique name will be created and returned if this is empty
---
string name
We can see from the output above that the spawn message takes three float32
values for its position and orientation as well a string
for its name. The
---
indicate the return value of the services. Unlike topics, services have
a return value, which enables them to do things like perform computations and
calculations.
Let's examine the help for calling a service by running ros2 service call --help
:
$ ros2 service call --help
usage: ros2 service call [-h] [-r N] service_name service_type [values]
Call a service
positional arguments:
service_name Name of the ROS service to call to (e.g. '/add_two_ints')
service_type Type of the ROS service (e.g. 'std_srvs/srv/Empty')
values Values to fill the service request with in YAML format (e.g.
"{a: 1, b: 2}"), otherwise the service request will be
published with default values
optional arguments:
-h, --help show this help message and exit
-r N, --rate N Repeat the call at a specific rate in Hz
The syntax here is very similar to publishing to a topic, but instead of using a
a topic name we use a service name. The service type is just like the topic type
that we used in the past, but instead of using a message type we need a service
type. Finally we give it a value in YAML format. A YAML string must be encased
in single quotes. Let's try calling a service by creating a turtle
named Larry
at a position where all values are zero (use TAB
complete).
$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 0, y: 0, theta: 0.0, name: 'Larry'}"
requester: making request: turtlesim.srv.Spawn_Request(x=0.0, y=0.0, theta=0.0, name='Larry')
response:
turtlesim.srv.Spawn_Response(name='Larry')
If everything is working correctly you should now have a turtle named "Larry" in the lower left hand corner of the screen:
Try exploring the other services offered, or creating more turtles at different locations and moving them around.
Let's move on to actions. As mentioned previously, actions differ from services in a few ways and offer a number of advantages. Actions have the following advantages:
- Actions have a
goal
. That is to say you send them a goal, and they attempt to complete it. - Actions can reject goal requests. This prevents them from becoming too busy.
- Actions are asynchronous and can perform tasks "while you wait."
- Actions will provide you with "updates" with information about their progress while you wait.
- Actions are preemptable, meaning you can cancel them if you change your mind.
Just like with services, we'll first figure out how to call the sole action in
our ROS system by using the action list
, action show
, and action info
commands. Recall, that when we called ros2 action list
we got a single
service. Now that we have Larry things have changed. Let's take a look:
$ ros2 action list
/Larry/rotate_absolute
/turtle1/rotate_absolute
Now there are two actions available, one for Larry and one for turtle1
.
Let's rotate turtle1 to face Larry. First we'll call action info
using /turtle1/rotate_absolute
as the input and see what we get:
$ ros2 action info /turtle1/rotate_absolute
Action: /turtle1/rotate_absolute
Action clients: 0
Action servers: 1
/turtlesim
Well, that tells us about the client and servers, but it really isn't
helpful for our goal of moving Larry. Why don't we look at the action send_goal
help and see if we can
figure out how to use it:
$ ros2 action send_goal --help
usage: ros2 action send_goal [-h] [-f] action_name action_type goal
Send an action goal
positional arguments:
action_name Name of the ROS action (e.g. '/fibonacci')
action_type Type of the ROS action (e.g.
'example_interfaces/action/Fibonacci')
goal Goal request values in YAML format (e.g. '{order: 10}')
optional arguments:
-h, --help show this help message and exit
-f, --feedback Echo feedback messages for the goal
This command needs an action name, an action type, and a goal in YAML. We know the action name, and we know how to write YAML, so all we need is to determine the action type. The best way to get the action type is the same way we published a message.
We see each of our turtles have one service called rotate_absolute
.
Let's dig into this action using the info
sub command. This command has a -t
flag to list the types of messages.
$ ros2 action info /turtle1/rotate_absolute -t
Action: /turtle1/rotate_absolute
Action clients: 0
Action servers: 1
/turtlesim [turtlesim/action/RotateAbsolute]
The first line lists the action
name. The second line gives the current number of clients for the
action. The Action servers
line gives the total number of action
servers for this action. The last line gives the package and message
type for the action.
We can see here that we need to know the action name, the type, and the values. Now the only problem is figuring out the format of the action type.
Let's understand the RotateAbsolute
action message
The ros2 interface show
command can be used to find the type of action
message. Let's take a look:
$ ros2 interface show turtlesim/action/RotateAbsolute
# The desired heading in radians
float32 theta #< --- This section is the GOAL
---
# The angular displacement in radians to the starting position
float32 delta #< --- This section is the final result, different from the goal.
---
# The remaining rotation in radians
float32 remaining # < --- This is the current state.
What does this say about rotate absolute?
- There is a float input,
theta
, the desired heading. This first section is the actual goal. delta
is the angle from the initial heading. This is the value returned when the action completes.remaining
is the remaining radians to move. This is the value posted by the action while the action is being done.
With this information we can create our call to the action server. We'll
use the -f
flag to make this a bit clearer. Keep an eye on your turtle! It should move, slowly.
$ ros2 action send_goal -f /turtle1/rotate_absolute turtlesim/action/RotateAbsolute {'theta: 1.70'}
Waiting for an action server to become available...
Sending goal:
theta: 1.7
Feedback:
remaining: 0.11599969863891602
Goal accepted with ID: 35c40e91590047099ae5bcc3c5151121
Feedback:
remaining: 0.09999966621398926
Feedback:
remaining: 0.06799960136413574
Feedback:
remaining: 0.03599953651428223
Result:
delta: -0.09600019454956055
Goal finished with status: SUCCEEDED
If everything worked correctly we should see our turtle has rotated.
ROS Parameters
In ROS, parameters are values that are shared between nodes in the system (if you are familiar with the blackboard design pattern in software engineering). Parameters are values that any node can query or write to. Another good analogy would be global constants in normal software programs. Parameters are best used to configure your robot. For example, if you were building an autonomous vehicle and wanted to cap the maximum velocity of the vehicle at 100 km/h, you could create a parameter called "MAX_SPEED" that is visible to all the nodes.
Let's take a look at the param
command by running ros2 param --help
.
$ ros2 param --help
Various param related sub-commands
Commands:
delete Delete parameter
get Get parameter
list Output a list of available parameters
set Set parameter
Call `ros2 param <command> -h` for more detailed usage.
At a high level, ROS 2's param
command has sub commands to get and set a variable,
along with a list
functionality, and a delete
command. As with most of the
other commands we've worked through, it is instructive to look at list
first. Let's see what the docs say about the list
command and then see what
happens when we call the sub command:
$ ros2 param list --help
usage: ros2 param list [-h] [--spin-time SPIN_TIME] [--include-hidden-nodes]
[--param-prefixes PARAM_PREFIXES [PARAM_PREFIXES ...]]
[node_name]
Output a list of available parameters
positional arguments:
node_name Name of the ROS node
optional arguments:
-h, --help show this help message and exit
--spin-time SPIN_TIME
Spin time in seconds to wait for discovery (only
applies when not using an already running daemon)
--include-hidden-nodes
Consider hidden nodes as well
--param-prefixes PARAM_PREFIXES [PARAM_PREFIXES ...]
Only list parameters with the provided prefixes
$ ros2 param list
/turtlesim:
background_b
background_g
background_r
use_sim_time
The only argument of note in this sub command is the node_name
which allows
you to narrow the scope of param list
to only those parameters used by a particular
node. In terms of parameters in the turtlesim
node, we see that our call to param list
gives us: three background color control params named
background_x
and a use_sim_time
parameter. To learn all about the param
command why don't we try to change these background color parameters using the
CLI.
The first step in changing the background color is to see what the current color
is. The param get
sub command requires both a node name and a parameter
name. In our list above we can see the node name as the top level element with
the forward slash in front of it, namely /turtlesim
. The syntax for param get
is ros2 param get <node_name> <param>
. Let's give it a whirl and see our
current background color values.
$ ros2 param get /turtlesim background_b
Integer value is: 255
$ ros2 param get /turtlesim background_g
Integer value is: 86
$ ros2 param get /turtlesim background_r
Integer value is: 69
On most computers color is represented as a triplet of <R,G,B> values. The color value of <69,86,255> corresponds to a periwinkle blue color. To change the color of the turtlesim we need to first set the parameter value and then reset the turtlesim to make it apply the color changes. We covered the basics of calling a service previously so we won't cover the steps of constructing a service call. Let's try setting our background color's blue component to 128.
$ ros2 param set turtlesim background_b 128
Set parameter successful
$ ros2 service call /reset std_srvs/srv/Empty
requester: making request: std_srvs.srv.Empty_Request()
response:
std_srvs.srv.Empty_Response()
If everything worked correctly your turtle should look like the screen below.
ROS Bags
ROS bags are ROS's tool for recording, and replaying data. ROS bags are like log files that let you store data along with messages. ROS systems can generate a lot of data, so when you bag data you must select which topics you want. Bags are a great tool for testing and debugging your application and a great tool for building robust unit tests.
Let's take a look at the root ROS Bag command by typing ros2 bag --help
into
the terminal. If you get an error you might need to install ROS Bag as it is
often in a separate package. On Linux you can run sudo apt install ros-eloquent-ros2bag
and it should automatically install the package for you.
$ ros2 bag -h
usage: ros2 bag [-h] Call `ros2 bag <command> -h` for more detailed usage. ...
Various rosbag related sub-commands
Commands:
info ros2 bag info
play ros2 bag play
record ros2 bag record
As you can see there are three sub commands, record
, play
, and info
. With these
commands you can record a bag file, play/replay a file you've recorded, and find information about a bag file.
Let's try recording our first bag file. To do this we'll need three terminals all
running ROS. The first terminal should already have our turtlesim running. If it
isn't running you can restart it with ros2 run turtlesim turtlesim_node
. Next
you'll need to start the draw_square
demo again to get the default turtle
moving. To do this run ros2 run turtlesim draw_square
. Now, in a third
terminal we can bag some data by running the bag command. Let's first look at
the record sub command by running ros2 bag record -h
$ ros2 bag record -h
usage: ros2 bag record [-h] [-a] [-o OUTPUT] [-s STORAGE]
[-f SERIALIZATION_FORMAT] [--no-discovery]
[-p POLLING_INTERVAL] [-b MAX_BAG_SIZE]
[topics [topics ...]]
ros2 bag record
positional arguments:
topics topics to be recorded
optional arguments:
-h, --help show this help message and exit
-a, --all recording all topics, required if no topics are listed
explicitly.
-o OUTPUT, --output OUTPUT
destination of the bagfile to create, defaults to a
timestamped folder in the current directory
-s STORAGE, --storage STORAGE
storage identifier to be used, defaults to "sqlite3"
-f SERIALIZATION_FORMAT, --serialization-format SERIALIZATION_FORMAT
rmw serialization format in which the messages are
saved, defaults to the rmw currently in use
--no-discovery disables topic auto discovery during recording: only
topics present at startup will be recorded
-p POLLING_INTERVAL, --polling-interval POLLING_INTERVAL
time in ms to wait between querying available topics
for recording. It has no effect if --no-discovery is
enabled.
-b MAX_BAG_SIZE, --max-bag-size MAX_BAG_SIZE
maximum size in bytes before the bagfile will be
split. Default it is zero, recording written in single
bagfile and splitting is disabled.
We can see from the help file that the syntax for recording a bag is to simply
give the sub command a list of topics to record. Most of the other arguments are
for more advanced users to help configure how and when data is stored. It is
worth noting that there is a -a, --all
command that records all the data. You
can also specify the output bag file with the -o, --output command
.
Let's go ahead and run our bag command, and let's bag the pose data on the
/turtle1/pose
topic and save it to the file turtle1.bag
using the -o
flag. Be aware that the program will continue bagging data until you hit
CTRL-C
, so give the command a good 30 seconds to collect data before you kill
it.
$ ros2 bag record /turtle1/pose -o turtle1
[INFO] [rosbag2_storage]: Opened database 'turtle1'.
[INFO] [rosbag2_transport]: Listening for topics...
[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/pose'
[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...
^C[INFO] [rclcpp]: signal_handler(signal_value=2)
Now that we collected our data let's inspect our bag file. You can introspect
any bag file using the ros2 bag info
command. This command will list the
messages in the bag, the duration of file, and the number of messages.
$ ros2 bag info turtle1
Files: turtle1.db3
Bag size: 268.4 KiB
Storage id: sqlite3
Duration: 68.705s
Start: May 4 2020 16:10:26.556 (1588633826.556)
End May 4 2020 16:11:35.262 (1588633895.262)
Messages: 4249
Topic information: Topic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 4249 | Serialization Format: cdr
Once you have collected a bag file you can replay the file just like a running system. Bags are a great tool for debugging and testing. You can treat a ROS bag like a recording of a running ROS system. When you play a bag file you can use most of the ros2 CLI tools to inspect the recorded topics.
To replay the bag, first use CTRL-C
to turn off the
turtlesim_node
and the draw_square
node. Now in a new terminal replay the bag
file using the following command:
$ ros2 bag play turtle1
[INFO] [rosbag2_storage]: Opened database 'turtle1'.
Nothing should happen visibly, but a lot is happening under the hood.
To see what is happening go to a second terminal. Just like a running robot,
you should be able to list
and echo
topics:
$ ros2 topic list
/parameter_events
/rosout
/turtle1/pose
$ ros2 bag info turtle1
x: 3.8595714569091797
y: 3.6481313705444336
theta: -1.2895503044128418
linear_velocity: 1.0
angular_velocity: 0.0
---
ROS2 Component Command
ROS2 Daemon Command
ROS2 Doctor Command
With any complex system problems can sometimes arise, and knowing how to describe your
system and what is happening can do a lot to help others help you fix your
problem. ROS 2 has a doctor
command that you can use to print a variety of
reports that you can use to help communicate the state of your system to others
trying to provide help. Whether it is one of your co-workers, a vendor, or an
on-line forum, providing detailed and complete information about your ROS system
can go a long way to solving your problem. Let's call --help
on the ROS 2
doctor command:
$ ros2 doctor --help
usage: ros2 doctor [-h] [--report | --report-failed] [--include-warnings]
Check ROS setup and other potential issues
optional arguments:
-h, --help show this help message and exit
--report, -r Print all reports.
--report-failed, -rf Print reports of failed checks only.
--include-warnings, -iw
Include warnings as failed checks. Warnings are
ignored by default.
As we can see from the help file we have a couple of report options. One option
is to print the full report with -r
, or just what failed with -rf
. If you're
running ros2 doctor -r
you should see a fairly lengthy report generated giving
information about your computer's operating system, your networking
configuration, and your running ROS system. If you ever run into an issue you
should always include this full report.
ROS 2 Interface
As you've already seen, ROS uses standard messages so that different packages and programs, potentially written in different programming languages, can all talk to one another. To make this all work, ROS uses standard messages, and communication protocols built on top of those standard messages. This can make finding type information about a particular message, service, or action difficult. To help developers write both CLI command calls and develop client code, the ROS CLI has the interface command. We've touched on this command briefly in other sections, as it is the go to tool for message type information.
To better understand the interface
command let's start by looking at its high
level help command to see what sub commands are available:
$ ros2 interface --help
usage: ros2 interface [-h]
Call `ros2 interface <command> -h` for more detailed
usage. ...
Show information about ROS interfaces
optional arguments:
-h, --help show this help message and exit
Commands:
list List all interface types available
package Output a list of available interface types within one package
packages Output a list of packages that provide interfaces
proto Output an interface prototype
show Output the interface definition
Call `ros2 interface <command> -h` for more detailed usage.
The interface command are all geared towards helping you understand
available message types. Let's examine the list
sub command in depth. list
will list all of the available messages, services, and actions on your
system. This command has flags that can help you narrow down the scope of your
search. Even a basic ROS installation has a lot of messages, so a tool you
should get familiar with is grep
. grep
lets you search through some text to
find what you are looking for quickly and easily. You can grep in a case
insensitive manner using the -i
flag followed by the text you want to search
for. We can tie this CLI tool to our interface tool by using the UNIX pipe operator |
. The example below
shows you how to use the list operation and then how to use it to search:
$ ros2 interface list --only-msgs
Messages:
action_msgs/msg/GoalInfo
action_msgs/msg/GoalStatus
... <DOZENS OF DIFFERENT TYPES> ...
visualization_msgs/msg/MarkerArray
visualization_msgs/msg/MenuEntry
$ ros2 interface list --only-msgs | grep -i point
geometry_msgs/msg/Point
geometry_msgs/msg/Point32
geometry_msgs/msg/PointStamped
map_msgs/msg/PointCloud2Update
pcl_msgs/msg/PointIndices
rcl_interfaces/msg/FloatingPointRange
sensor_msgs/msg/PointCloud
sensor_msgs/msg/PointCloud2
sensor_msgs/msg/PointField
trajectory_msgs/msg/JointTrajectoryPoint
Using grep to search through CLI output is a common tactic used by developers to
find just the specific information they need. The next two sub commands
package
and packages
can be used to first determine what ROS packages are on
your system, and then to drill down into an individual package to determine what
messages are in that package. Note that
you can use grep
just like before to search for your specific interest. The
example below shows you how to first determine if std_msgs
is installed and
then to find out what sort of array types it contains:
$ ros2 interface packages
action_msgs
action_tutorials_interfaces
actionlib_msgs
builtin_interfaces
composition_interfaces
diagnostic_msgs
example_interfaces
geometry_msgs
lifecycle_msgs
logging_demo
map_msgs
nav_msgs
pcl_msgs
pendulum_msgs
rcl_interfaces
rosgraph_msgs
rqt_py_common
sensor_msgs
shape_msgs
std_msgs
std_srvs
stereo_msgs
tf2_msgs
trajectory_msgs
turtlesim
unique_identifier_msgs
visualization_msgs
kscottz@kscottz-ratnest:~/Code/ros2multirobotbook/src$ ros2 interface package std_msgs | grep -i array
std_msgs/msg/Int8MultiArray
std_msgs/msg/Int32MultiArray
std_msgs/msg/MultiArrayLayout
std_msgs/msg/UInt64MultiArray
std_msgs/msg/Float32MultiArray
std_msgs/msg/UInt16MultiArray
std_msgs/msg/UInt32MultiArray
std_msgs/msg/Int16MultiArray
std_msgs/msg/ByteMultiArray
std_msgs/msg/Int64MultiArray
std_msgs/msg/Float64MultiArray
std_msgs/msg/UInt8MultiArray
std_msgs/msg/MultiArrayDimension
The next two commands are particularly
helpful and you should remember them as they will make your life much easier. As
we have discussed previously all message publication, service calls, and action
calls in the CLI take in both the message type and data you want to transmit in
YAML format. But what if you don't know the message format, and you don't know a lot about
YAML? The interface show
and interface proto
commands make this process
easier by respectively telling you first the message type and then the message
format. Recall earlier in the chapter when we called the spawn
service on
our turtle simulation. We can use interface show
to tell us broadly about the
service and what each of the values mean. We can then use interface proto
,
short for prototype, to then generate an empty message that we can fill
out. See the example below:
$ ros2 interface show turtlesim/srv/Spawn
float32 x
float32 y
float32 theta
string name # Optional. A unique name will be created and returned if this is empty
---
string name
$ ros2 interface proto turtlesim/srv/Spawn
"x: 0.0
y: 0.0
theta: 0.0
name: ''
"
$ ros2 service call /spawn turtlesim/srv/Spawn "{<copy and paste proto here>}"
You can see from the example above how handy these tools can be. It is worth
noting that you need to paste the prototype into a set of quotes and curly
braces for the call to work "{<prototype>}"
.
ROS 2 Launch
The launch
command is used to run ROS launch files. Up until this point we've
been running single ROS programs by hand using the run
command, however this
is not how larger ROS systems are generally operated and many robots command
tens if not hundreds of small programs. The ROS launch command is different from
most of the other ROS commands in that it has no sub commands and has a single
function, to start a ROS launch file that executes multiple of programs.
To illustrate this command let's take a look at
its help file.
$ ros2 launch -h
usage: ros2 launch [-h] [-d] [-p | -s] [-a]
package_name [launch_file_name]
[launch_arguments [launch_arguments ...]]
Run a launch file
positional arguments:
package_name Name of the ROS package which contains the launch file
launch_file_name Name of the launch file
launch_arguments Arguments to the launch file; '<name>:=<value>' (for
duplicates, last one wins)
optional arguments:
-h, --help show this help message and exit
-d, --debug Put the launch system in debug mode, provides more
verbose output.
-p, --print, --print-description
Print the launch description to the console without
launching it.
-s, --show-args, --show-arguments
Show arguments that may be given to the launch file.
-a, --show-all-subprocesses-output
Show all launched subprocesses' output by overriding
their output configuration using the
OVERRIDE_LAUNCH_PROCESS_OUTPUT envvar.
Launch files are usually included with a ROS package and are commonly stored in a
launch
sub directory. Modern launch files are usually written in Python and end
with the *.launch.py
file extension. The launch
command has two arguments,
the first one is the package name and then the launch file name. If you are unaware
of the launch files in your package you can use tab completion to list all the
available launch files. Finally, some launch files have arguments that can be
appended to the command. If you are unsure about what a launch file does, or
what arguments it needs, the --print
and --show-args
commands will tell you
this information. Let's read up on the multisym.launch.py
launch file and then
run it following the example below (end the simulation with CTRL-C
):
$ ros2 launch turtlesim multisim.launch.py --show-args
Arguments (pass arguments as '<name>:=<value>'):
No arguments.
$ ros2 launch turtlesim multisim.launch.py --print
<launch.launch_description.LaunchDescription object at 0x7f75aab63828>
├── ExecuteProcess(cmd=[ExecInPkg(pkg='turtlesim', exec='turtlesim_node'), '--ros-args'], cwd=None, env=None, shell=False)
└── ExecuteProcess(cmd=[ExecInPkg(pkg='turtlesim', exec='turtlesim_node'), '--ros-args'], cwd=None, env=None, shell=False)
$ ros2 launch turtlesim multisim.launch.py
[INFO] [launch]: All log files can be found below /home/kscottz/.ros/log/2020-06-24-14-39-03-312667-kscottz-ratnest-20933
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [turtlesim_node-1]: process started with pid [20944]
[INFO] [turtlesim_node-2]: process started with pid [20945]
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)
ROS 2 Lifecycle
ROS 2 has a new feature called lifecycle
which allows for greater control over
the state of a ROS node. Roughly, this feature allows nodes to have complex
start-up and shut-down procedures that are correctly handed. An example of such
a node would be one that controls a sensor or actuator that needs to perform a
power-on self-test or calibration procedure prior to running. The ROS design
docs
give a great primer on the states and transitions in a lifecycle
node. Let's look at the
lifecycle
command to determine what sub commands are available:
$ ros2 lifecycle -h
usage: ros2 lifecycle [-h]
Call `ros2 lifecycle <command> -h` for more detailed
usage. ...
Various lifecycle related sub-commands
optional arguments:
-h, --help show this help message and exit
Commands:
get Get lifecycle state for one or more nodes
list Output a list of available transitions
nodes Output a list of nodes with lifecycle
set Trigger lifecycle state transition
Call `ros2 lifecycle <command> -h` for more detailed usage.
The nodes
sub command will list all the lifecycle nodes on a given system.
Once you have listed the nodes, you can list each node's available
transitions using ros2 lifecycle list <nodename>
. These transitions are
dictated by the node's current state with some states having more transitions
available than others. If instead of available transitions you wish to query the
current state you can use lifecycle get
to return the current state of
your target node. Once you have satisfactorily determined the state of the node
and the available transitions, the lifecycle set
command can be used to trigger
the node to transition to a new state. Generally, these CLI commands are used to
diagnose failure modes of systems, or to manually transition a particular
component.
ROS 2 msg (Message)
ROS 2 Eloquent is the last version of ROS to use the msg
command. All of the
commands in msg
are mirrored in the interface
command. These features are
currently deprecated and will be removed in Foxy.
ROS 2 pkg (Package)
The ROS 2 package command is a very useful command to understand what ROS
packages are installed on your system, where they are installed, and the
executables contained within each package. These tools are particularly useful
for understanding an existing robot configuration and finding tools that are
only used on occasion. Let's start by taking a look at the help file for the pkg
command:
$ ros2 pkg -h
usage: ros2 pkg [-h] Call `ros2 pkg <command> -h` for more detailed usage. ...
Various package related sub-commands
optional arguments:
-h, --help show this help message and exit
Commands:
create Create a new ROS2 package
executables Output a list of package specific executables
list Output a list of available packages
prefix Output the prefix path of a package
xml Output the XML of the package manifest or a specific tag
Call `ros2 pkg <command> -h` for more detailed usage.
This command has a variety of sub commands, many of which should look fairly
familiar at this point. The list
sub command acts in a manner very similar to
list
sub commands we have discussed previously, but this one only lists the
installed system packages. This sub command is often used with grep
to help you
find out if a particular package is installed.
Once you have located an installed package you can then have it list the
executables contained by the package using the executables
command. This is
much more practical than finding the executables manually. The sub command takes
in a single argument which is the package name. The executables command has a
single optional argument, --full-path
, which will output the full path to all
the executable programs. The example below shows how to use these
commands to check the path for all of the turtlesim executables:
$ ros2 pkg list | grep turtle
turtlesim
$ ros2 pkg executables turtlesim --full-path
/opt/ros/eloquent/lib/turtlesim/draw_square
/opt/ros/eloquent/lib/turtlesim/mimic
/opt/ros/eloquent/lib/turtlesim/turtle_teleop_key
/opt/ros/eloquent/lib/turtlesim/turtlesim_node
If you just wanted to know the path to the turtlesim executables you could use
the prefix
sub command, which returns the path for a given package's
executables.
Each ROS package contains an XML file that contains metadata for the package,
including information such as the license, maintainer, and its dependencies. ROS
pkg has a handy xml
sub command to print these files to the screen, saving you
the hassle of locating and opening the file. You can use grep
on the output of
this command to get just the info you need. Below is an example of xml
and prefix
used to find
the directory of turtlesim, its maintainer, and its license:
$ ros2 pkg prefix turtlesim
/opt/ros/eloquent
$ ros2 pkg xml turtlesim | grep maintainer
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
$ ros2 pkg xml turtlesim | grep license
<license>BSD</license>
kscottz@kscottz-ratnest:~$
The last sub command in the pkg
command is create
. create
is a tool to help
you create a ROS package. We'll use this sub command later in the chapter to
create a new ROS package. The short of it is that you feed the command your
package name and all of the relevant information for your package as optional
arguments.