Lab 1 Intro To ROS
Lab 1 Intro To ROS
Goals
By the end of this lab you should be able to:
• Set up a new ROS environment, including creating a new workspace and creating a package with the appropriate
dependencies specified
• Use the catkin tool to build the packages contained in a ROS workspace
• Run nodes using rosrun
• Use ROS’s built-in tools to examine the topics and services used by a given node
If you get stuck at any point in the lab you may submit a help request during your lab section at tinyurl.com/106alab.
Note: Much of this lab is borrowed from the official ROS tutorials. We picked out the material you will find most
useful in this class, but feel free to explore other resources if you are interested in learning more.
Contents
1 What is ROS? 2
1.1 Computation graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 File system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Initial configuration 3
Fall 2014.
1
7 Understanding ROS services 11
7.1 Using rosservice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
7.2 Calling services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1 What is ROS?
The ROS website says:
ROS is an open-source, meta-operating system for your robot. It provides the services you would ex-
pect from an operating system, including hardware abstraction, low-level device control, implementation
of commonly-used functionality, message-passing between processes, and package management. It also
provides tools and libraries for obtaining, building, writing, and running code across multiple computers.
The ROS runtime “graph” is a peer-to-peer network of processes that are loosely coupled using the ROS
communication infrastructure. ROS implements several different styles of communication, including syn-
chronous RPC-style communication over services, asynchronous streaming of data over topics, and storage
of data on a Parameter Server.
This isn’t terribly enlightening to a new user, so we’ll simplify a little bit. For the purposes of this class, we’ll be
concerned with two big pieces of ROS’s functionality: the computation graph and the file system.
A typical robotic system has numerous sensing, actuation, and computing components. Consider a two-joint manipu-
lator arm for a pick-and-place task. This system might have:
• Two motors, each connected to a revolute joint
A useful abstraction for many robotic systems is to divide the control software into various low-level, independent
control loops that each manage a single task on the robot, then couple these low level loops together with higher-level
logic. In our example system above, we might divide the control software into:
2
• Two control loops (one for each joint) that, given a position or velocity command, control the power applied to
the joint motor based on position sensor measurements at the joint
• Another control loop that receives commands to open or close the gripper, then switches the gripper motor on
and off while controlling the power applied to it to avoid crushing objects
• A sensing loop that reads individual images from the camera at 30 Hz
• A sensing loop that reads the output of the IR distance sensor at 100 Hz
• A single high-level module that performs the supervisory control of the whole system
Given this structure for the robot’s software, the control flow for the pick-and-place task could be the following: The
high-level supervisor queries the camera sensing loop for a single image. It uses a vision algorithm to compute the
location of the object to grasp, then computes the joint angles necessary to move the manipulator arm to this location
and sends position commands to each of the joint control loops telling them to move to this position. As the arm
nears the target, the supervisor queries the IR sensor loop for the distance to the object at a rate of 5 Hz and issues
several more fine motion commands to the joint control loops to position the arm correctly. Finally, the supervisor
signals the gripper control loop to close the gripper.
An important feature of this design is that the supervisor need not know the implementation details of any of the
low-level control loops. It interacts with each only through simple control messages. This encapsulation of functional-
ity within each individual control loop makes the system modular, and makes it easier to reuse the same code across
many robotic platforms.
The ROS computation graph lets us build this style of software easily. In ROS, each individual control loop is a node
within the computation graph. A node is simply an executable file that performs some task. Nodes exchange control
messages, sensor readings, and other data by publishing or subscribing to topics or by sending requests to services
offered by other nodes (these concepts will be discussed in detail later in the lab).
Nodes can be written in a variety of languages, including Python and C++, and ROS transparently handles the details
of converting between different datatypes, exchanging messages between nodes, etc.
2 Initial configuration
The lab machines you’re using already have ROS and the Baxter robot SDK installed, but you’ll need to perform a
few user-specific configuration tasks the first time you log in with your class account.
Open the .bashrc file, located in your home directory (denoted “ ~ ”), in a text editor. (If you don’t have a
preferred editor, we recommend Sublime Text, which is preinstalled on lab computers and can be accessed using
subl <filename>. Append the following to the contents (copying from the pdf will not insert newlines, copy from
the example bashrc link below)
#######################
# Sourcing the Robots #
#######################
# If you are working with the Baxter or Sawyer packages, uncomment the line below
# to source the .bashrc file that sets up ROS with the Baxter and Sawyer packages:
source /scratch/shared/baxter_ws/devel/setup.bash
3
that sets up ROS without the Baxter and Sawyer packages:
# source /opt/ros/kinetic/setup.bash
##############################
# Configuring the IP Address #
##############################
# Uncomment the line below with the correct IP address for the robot that you will be using.
# For example, export ROS_MASTER_URI=http://192.168.1.111:11311 to work with Black Turtlebot.
# export ROS_MASTER_URI=http://[IP_ADDR_OF_ROBOT]:11311
You can see an example of what the bashrc will look like on a lab computer by examining this file.
Save and close the file when you’re done editing, then execute the command
source ~/.bashrc
The “source /scratch/shared/baxter_ws/devel/setup.bash” line does two things. Firstly, it tells Ubuntu to run
a ROS-specific configuration script every time you open a new terminal window. This script sets several environment
variables that tell the system where the ROS installation is located. Secondly, it edits the $ROS_PACKAGE_PATH envi-
ronment variable.
This variable is particularly important, as it tells ROS which directories to search for software packages. Any code
you want to run with ROS must be located beneath one of the directories specified in the list. By default, ROS’s
setup.bash file adds the directories for all of ROS’s built-in packages to the package path. However, the Baxter SDK
contains additional packages that we want to be able to run, so we must add its directory to the package path as well.
The SDK is located in the /scratch/shared directory.
The “source /opt/ros/kinetic/setup.bash” line sets all the path variables to use the ROS built-in packages, but
it does not clutter your workspace with the things associated with the Baxter SDK.
When you create your own workspaces, you will need to run a workspace specific setup.bash file to ensure that your
packages are located on the ROS path (we will discuss this in more detail in Section 4).
After you source the robots, we must configure the IP addresses of the workstations and the robots so they can com-
municate with each other. The ROS_HOSTNAME should be set to the IP address of the workstation. This is done for
you.
Additionally, if you are using any of the Turtlebots, you will need to set the $ROS_MASTER_URI to the IP address of
the robot. This variable effectively tells nodes where to look for the master node.
4
3.1 Anatomy of a package
cd into /scratch/shared/baxter_ws/src/baxter_examples. The baxter_examples package contains several exam-
ple nodes which demonstrate the motion control features of Baxter. The folder contains several items:
• /src - source code for nodes
• package.xml - the package’s configuration and dependencies
• /launch - launch files that start ROS and relevant packages all at once
• /scripts - another folder to store nodes
Other packages might contain some additional items:
• /lib - extra libraries used in the package
• /msg and /srv - message and service definitions which define the protocols nodes use to exchange data
Open the package.xml file with the command subl package.xml. It should look something like this:
<?xml version="1.0"?>
<package>
<name>baxter_examples</name>
<version>1.2.0</version>
<description>
Example programs for Baxter SDK usage.
</description>
<maintainer email="[email protected]">
Rethink Robotics Inc.
</maintainer>
<license>BSD</license>
<url type="website">http://sdk.rethinkrobotics.com</url>
<url type="repository">
https://github.com/RethinkRobotics/baxter_examples
</url>
<url type="bugtracker">
https://github.com/RethinkRobotics/baxter_examples/issues
</url>
<author>Rethink Robotics Inc.</author>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>rospy</build_depend>
<build_depend>xacro</build_depend>
<build_depend>actionlib</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>control_msgs</build_depend>
<build_depend>trajectory_msgs</build_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>dynamic_reconfigure</build_depend>
<build_depend>baxter_core_msgs</build_depend>
<build_depend>baxter_interface</build_depend>
<run_depend>rospy</run_depend>
<run_depend>xacro</run_depend>
<run_depend>actionlib</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>control_msgs</run_depend>
<run_depend>trajectory_msgs</run_depend>
<run_depend>cv_bridge</run_depend>
5
<run_depend>dynamic_reconfigure</run_depend>
<run_depend>baxter_core_msgs</run_depend>
<run_depend>baxter_interface</run_depend>
</package>
Along with some metadata about the package, the package.xml specifies 11 packages on which baxter_examples
depends. The packages with <build_depend> are the packages used during the build phase and the ones with
<run_depend> are used during the run phase. The rospy dependency is important - rospy is the ROS library
that Python nodes use to communicate with other nodes in the computation graph. The corresponding library for
C++ nodes is roscpp.
Note: To get info on the options and functionality of many ROS command line utilities, run the utility plus “help”
(e.g., just run “rospack help”).
Next, let’s test out a couple more convenient commands for working with packages. Run
rosls baxter_examples
and then
roscd baxter_examples
The function of these commands should become apparent quickly. Any ideas what they do?
For this lab, begin by creating a directory for the workspace. Create the directory by running the following command
from your home folder (~):
mkdir -p ros_workspaces/lab1
The directory “ros_workspaces” will eventually contain several lab-specific workspaces (named /lab1, /lab2, etc.)
After you fill /src with packages, you can build them by running “catkin_make” from the workspace directory (/lab1
in this case). Try running this command now, just to make sure the build system works. You should notice two new
directories alongside src: build and devel. ROS uses these directories to store information related to building your
6
packages (in build) as well as automatically generated files, like binary executables and header files (in devel).
Two other useful commands to know are rmdir to remove an empty directory and rm -r to remove a non-empty
directory.
catkin_create_pkg foo
Examine the contents of your newly created package, and open its package.xml file. By default, you will see that the
only dependency created is for the catkin tool itself:
<buildtool_depend>catkin</buildtool_depend>
Next, we’ll try the same command, but we’ll specify a few dependencies for our new package. Return to the src
directory and run the following command:
Examine the package.xml file for the new package and verify that the dependencies have been added. You’re now
ready to add source code, message and service definitions, and other resources to your project.
catkin_make
catkin_make builds all the packages and their dependencies in the correct order. If everything worked, catkin_make
should print a bunch of configuration and build information for your new packages “foo” and “bar”, with no errors.
You should also notice that the devel directory contains a script called “setup.bash.” “Sourcing” this script will
prepare your ROS environment for using the packages contained in this workspace (among other functions, it adds
“~/ros_workspaces/lab1/src” to the $ROS_PACKAGE_PATH). Run the commands
echo $ROS_PACKAGE_PATH
source devel/setup.bash
echo $ROS_PACKAGE_PATH
and note the difference between the output of the first and second echo.
Note: Any time that you want to use a non-built-in package, such as one that you have created, you will need to
source the devel/setup.bash file for that package’s workspace.
7
To summarize what we’ve done, here’s what your directory structure should look like:
ros_workspaces
lab1
build
devel
setup.bash
src
CMakeLists.txt
foo
CMakeLists.txt
package.xml
bar
CMakeLists.txt
package.xml
include
src
Checkpoint 1
Submit a checkoff request at tinyurl.com/106alab for a staff member to come and check off your work. At this point
you should be able to:
• Explain the contents of your ~/.bashrc file
8
5 Understanding ROS nodes
We’re now ready to test out some actual software running on ROS. First, a quick review of some computation graph
concepts:
• Node: an executable that uses ROS to communicate with other nodes
• Message: a ROS datatype used to exchange data between nodes
• Topic: nodes can publish messages to a topic as well as subscribe to a topic to receive messages
Now let’s test out some built-in examples of ROS nodes.
roscore
This starts a server that all other ROS nodes use to communicate. Leave roscore running and open a second terminal
window (Ctrl+Shift+T (new tab) or Ctrl+Shift+N (new window)).
As with packages, ROS provides a collection of tools we can use to get information about the nodes and topics that
make up the current computation graph. Try running
rosnode list
This tells us that the only node currently running is /rosout, which listens for debugging and error messages published
by other nodes and logs them to a file. We can get more information on the /rosout node by running
whose output shows that /rosout publishes the /rosout_agg topic, subscribes to the /rosout topic, and offers the
/set_logger_level and /get_loggers services.
The /rosout node isn’t very exciting. Let’s look at some other built-in ROS nodes that have more interesting behavior.
The ROS equivalent of a “hello world” program is turtlesim. To run turtlesim, we first want to start the turtlesim_node
executable, which is located in the turtlesim package, so we open a new terminal window and run
A turtlesim window should appear. Repeat the two rosnode commands from above and compare the results. You
should see a new node called /turtlesim that publishes and subscribes to a number of additional topics.
You should now be able to drive your turtle around the screen with the arrow keys when in this terminal window.
9
6.1 Using rqt graph
Let’s take a closer look at what’s going on here. We’ll use a tool called rqt_graph to visulize the current computation
graph. Open a new terminal window and run
This should produce an illustration like Figure 2. In this example, the teleop_turtle node is capturing your keystrokes
and publishing them as control messages on the /turtle1/cmd_vel topic. The /turtlesim node then subscibes to
this same topic to receive the control messages.
Now move the turtle with the arrow keys and observe the messages published on the topic. Return to your rqt_graph
window, and click the refresh button (blue circle arrow icon in the top left corner). You should now see that a second
node (the rostopic node) has subscribed to the /turtle1/cmd_vel topic, as shown in Figure 3.
Figure 3: Output of rqt graph when running turtlesim and viewing a topic using rostopic echo.
While rqt_graph only shows topics with at least one publisher and subscriber, we can view all the topics published
or subscribed to by all nodes by running
rostopic list
10
For even more information, including the message type used for each topic, we can use the verbose option:
rostopic list -v
rosservice list
We can also see what type of data is included in a request/response for a service. Check the service type for the
/clear service by running
This tells us that the service is of type std_srvs/Empty, which means that the service does not require any data as
part of its request, and does not return any data in its response.
Because the /clear service does not take any input data, we can call it without arguments
If we look back at the turtlesim window, we see that our call has cleared the background.
We can also call services that require arguments. Use rosservice type to find the datatype for the /spawn service.
The query should return turtlesim/Spawn, which tells us that the service is of type Spawn, and that this service type
is defined in the turtlesim package. Use rospack find turtlesim to get the location of the turtlesim package
(hint: you could also use “roscd” to navigate to the turtlesim package), then open the Spawn.srv service definition,
located in the package’s /srv subfolder. The file should look like
float32 x
float32 y
float32 theta
string name
---
string name
11
This definition tells us that the /spawn service takes four arguments in its request: three decimal numbers giving the
position and orientation of the new turtle, and a single string specifying the new turtle’s name. The second portion of
the definition tells us that the service returns one data item: a string with the new name we specified in the request.
Now let’s call the /spawn service to create a new turtle, specifying the values for each of the four arguments, in order:
The service call returns the name of the newly created turtle, and you should see the second turtle appear in the
turtlesim window.
Checkpoint 2
Submit a checkoff request at tinyurl.com/106alab for a staff member to come and check off your work. At this point
you should be able to:
• Explain what a node, topic, and message are
• Drive your turtle around the screen using arrow keys
• To log out, use the command pkill -u [username]. where [username] is your login credential. This will close
out every process on your account before logging you out.
12