Lecture 2
Lecture 2
• Low level device control: Robot software needs to be compatible with a wide
variety of input and output devices: GPIO (general purpose input/output)
pins, USB, SPI among others. C, C++ and Python all work well with low-level
devices, so robot software needs to support either of these languages, if not
all.
• High level Object Oriented Programming (OOP): In OOP, codes are encapsu-
lated, inherited, and reused as multiple instances. Ability to reuse codes and
develop programs in independent modules makes it easy to maintain code
for complex robots.
Until the advent of ROS, it was impossible for various robotics developers to
collaborate or share work among different teams, projects or platforms. In
2007, early versions of ROS started to be conceived with the Stanford AI Robot
(STAIR) project, which had the following vision:
• The new robot development environment should be free and open-source for
everyone, and need to remain so to encourage collaboration of community
members.
• The new platform should make core components of robotics – from its hard-
ware to library packages – readily available for anyone who intends to launch
a robotics project.
• Message passing: ROS provides a message passing interface that allows nodes
(i.e. programs) to communicate with each other. For example, one node
might detect edges in a camera image, then send this information to an ob-
ject recognition node, which in turn can send information about detected
obstacles to a navigation module.
Before jumping into using the functions and tools that ROS provides it is crit-
ical to understand a little more about how ROS operates. In particular, it is
important to know that ROS uses a publish/subscribe (pub/sub) structure for
communicating between different components or modules. This pub/sub struc-
ture (graphically shown in Figure 24.2) allows messages to be passed in between
components or modules through a shared virtual “chat room”. To support this
structure there are four primary components of ROS:
1. Nodes: the universal name for the individual components or modules that
need to send or receive information,
2. Messages: the object for holding information that needs communicated be-
tween nodes,
24.3.1 Nodes
Definition 24.3.1 (Node). A node10 is a process that performs computation. Nodes 10
http://wiki.ros.org/Nodes
principles of robot autonomy 5
are combined together to communicate with one another using streaming topics, RPC
services, and the Parameter Server.
Nodes are the basic building block of ROS that enables object-oriented robot
software development. Each robot component is developed as an individual
encapsulated unit of nodes, which are later reused and inherited, and a typical
robot control system will be comprised of many nodes. The use of indepen-
dent nodes, and their ability to be reused and inherited, greatly simplifies the
complexity of the overall software stack.
For example, suppose a robot is equipped with a camera and you want to
find an object in the environment and drive to it. Examples of nodes that might
be developed for this task are: a camera node that takes the image and pre-
processes it, an edge_detection node that takes the pre-processed image data
and runs an edge detection algorithm, a path_planning node that plans a path
between two points, and so on.
At the individual level, nodes are responsible for publishing or subscribing
to certain pieces of information that are shared among all other nodes. In ROS,
the pieces of information are called “messages" and they are shared in virtual
chat rooms called “topics".
24.3.2 Messages
Definition 24.3.2 (Messages). Nodes communicate with each other by publishing
simple data structures to topics. These data structures are called messages11 . 11
http://wiki.ros.org/Messages
A message is defined by field types and field names. The field type defines
the type of information the message stores and the name is how the nodes ac-
cess the information. For example, suppose a node wants to publish two inte-
gers x and y, a message definition might look like:
int32 x
int32 y
where int32 is the field type and x/y is the field name. While int32 is a prim-
itive field type, more complex field types can also be defined for specific appli-
cations. For example, suppose a sensor packet node publishes sensor data as an
array of a user-defined SensorData object. This message, called SensorPacket,
could have the following fields:
time stamp
SensorData [] sensors
uint32 length
In this case SensorData is a user-defined field type and the empty bracket [] is
appended to indicate that field is an array of SensorType objects.
More generally, field types can be either the standard primitive types (integer,
floating point, boolean, etc.), arrays of primitive types, or other user-defined
types. Messages can also include arbitrarily nested structures and arrays as well.
6 the robot operating system
Primitive message types available in ROS are listed below in Table 24.1. The first
column contains the message type, the second column contains the serialization
type of the data in the message and the third column contains the numeric type
of the message in Python.
24.3.3 Topics
Definition 24.3.3 (Topics). Topics12 are named units over which nodes exchange 12
http://wiki.ros.org/Topics
messages.
A given topic will have a specific message type associated with it, and any
node that either publishes or subscribes to the topic must be equipped to handle
that type of message. The command rostopic type <topic> can be used to
see what kind of message is associated with a particular topic. Any number of
nodes can publish or subscribe to a given topic.
Fundamentally, topics are for unidirectional, streaming communication. This
is perhaps not well suited for all types of communication, such as communica-
tion that demands a response (i.e. a service routine).
The rostopic command line tool can be used in several ways to monitor
active topics/messages. Three of the most common rostopic commands are:
24.3.4 Master
Definition 24.3.4 (Master). The master is a process that can run on any piece of
hardware to track publishers and subscribers to topics as well as services in the ROS
system.
import rospy
from std_msgs .msg import String
if __name__ == ’__main__ ’:
try:
talker ()
except rospy. ROSInterruptException :
pass
8 the robot operating system
will be included in every Python ROS Node at the top of the file. This line
makes sure your script is executed as a Python script.
import rospy
from std_msgs .msg import String
Note that the library rospy must be imported when writing a ROS Node. The
std_msgs.msg import enables the use of the std_msgs/String message type (a
simple string container) for publishing string messages.
which creates a node called “talker” and defines the talker’s interface to the rest
of ROS. In particular:
• rospy.init_node(NAME, ...) tells rospy the name of the node. Until rospy
has this information, it cannot start communicating with the ROS Master. In
this case, your node will take on the name talker. NOTE: the name must be a
base name (i.e. it cannot contain any slashes “/”).
• anonymous=True is a flag that tells rospy to generate a unique name for the
node, since ROS requires that each node have a unique name. If a node with
the same name comes up, it bumps the previous one so that malfunctioning
nodes can easily be kicked off the network. This makes it easy to run multi-
ple talker.py nodes.
• anonymous = True is another flag that ensures that the node has a unique
name by adding random numbers to the end of NAME.
defines a ROS rate that can be used to time how often the node publishes. In
particular, rospy.get_param(param_name, default_value) reads a private ROS
parameter (indicated by ‘∼’) called rate. This rate value is then used to create
a Rate object ros_rate in the second line. The Rate object’s sleep() method
offers a convenient way for looping at the desired frequency. For example, if
rate is 10, ROS should go through the loop 10 times per second (as long as the
processing time does not exceed 1/10th of a second!).
The line:
The loop:
!/ usr/bin/env python
import rospy
from std_msgs .msg import String
rospy .spin ()
if __name__ == ’__main__ ’:
listener ()
The code for listener.py is similar to talker.py, except that a new callback-
based mechanism for subscribing to messages is introduced.
declare that the node subscribes to the “chatter” topic, which is of type std_msgs.msgs.String.
When new messages are received, the function callback is invoked with the
message as the first argument.
The line:
rospy .spin ()
then simply keeps the node from exiting until the node has been shutdown.
$ cd ~/ catkin_ws
$ catkin_make
$ python talker .py
$ python listener .py
Definition 24.5.1. Launch files are .launch files with a specific XML format that can
be placed anywhere within a package directory to initialize multiple nodes, configuration
files, and a master.
principles of robot autonomy 11
In this line, pkg points to the package associated with the node that is to be
launched, type refers to the name of the node executable file, and the name of
the node can be overwritten with the name argument (this will take priority
over the name that is given to the node in the code). For example,
<node name =" bar1" pkg =" foo_pkg " type =" bar" />
launches the bar node from the foo_pkg package with a new name, bar1. Alter-
natively,
<node name =" listener1 " pkg =" rospy_tutorials " type =" listener .py"
args="−− test" respawn =" true" />
launches the listener1 node using the listener.py executable from the rospy_tutorials
package with the command-line argument -test. Additionally, if the node dies
it will automatically be respawned.
There are other attributes that can be set when starting a node. While only
args and respawn were introduced in this section, http://wiki.ros.org/
roslaunch/XML/node is a great resource for additional parameters that can be
used in the <node> tag.
catkin14 is a build system that compiles ROS packages. While catkin’s work- 14
catkin refers to the tail-shaped flower
flow15 is very similar to CMake’s, catkin adds support for automatic ‘find cluster on willow trees – a reference
to Willow Garage where, catkin was
package’ infrastructure, for building multiple, dependent projects at the same created.
15
time, and also supports both C and Python. http://wiki.ros.org/catkin/
conceptual_overview
When developing with ROS, catkin should be run whenever a new project
is started, or if there are any additions to packages. This is accomplished by
creating a directory called catkin_ws and then running the compile command
catkin_make in that directory:
Once the catkin workspace is compiled, it will automatically contain the files
CMakeLists.txt and package.xml. There are other sub-folders in catkin_ws as
well, as shown in Figure 24.3, which can be changed as needed.
12 the robot operating system
24.5.4 Gazebo
Gazebo16 is a popular 3D dynamic simulator with the ability to accurately and 16
http://gazebosim.org
[1] L. Joseph. Robot Operating System (ROS) for Absolute Beginners: Robotics
Programming Made Easy. Apress, 2018.
[2] M. Quigley, B. Gerkey, and W. D. Smart. Programming Robots with ROS: A
Practical Introduction to the Robot Operating System. O’Reilly Media, 2015.