Jethro's Braindump

Robot Operating System (ROS)

Introduction to ROS

What is ROS? <a id=“b049e1028daa027cae7888fe4de0456c” href=“#nilil_ros_introd_ros_wiki” title=“@misc{nilil_ros_introd_ros_wiki,

author = {nil}, howpublished = {}, note = {Online; accessed 15 October 2019}, title = {ROS/Introduction - ROS Wiki}, year = {nil}, }“>@misc{nilil_ros_introd_ros_wiki, author = {nil}, howpublished = {}, note = {Online; accessed 15 October 2019}, title = {ROS/Introduction - ROS Wiki}, year = {nil}, } {#what-is-ros-a-id-b049e1028daa027cae7888fe4de0456c-href-nilil-ros-introd-ros-wiki-title-misc-nilil-ros-introd-ros-wiki-author-nil-howpublished-http-wiki-dot-ros-dot-org-ros-introduction-note-online-accessed-15-october-2019-title-ros-introduction-ros-wiki-year-nil-misc-nilil-ros-introd-ros-wiki-author-nil-howpublished-http-wiki-dot-ros-dot-org-ros-introduction-note-online-accessed-15-october-2019-title-ros-introduction-ros-wiki-year-nil-a}

  • Left :B_column:

    • Meta-operating system, providing low level services:
      • process communication over a network
      • device control
      • hardware abstraction
    • Distributed framework of processes
  • Right :B_column:

Why use ROS?

  • “Lightweight” framework that speeds up large-scale robotic development
  • Many libraries developed on top of this framework that can be reused:

ROS Concepts

  • Computational Graph

    • All computation is organized as a peer-to-peer network of communicating processes.
  • Nodes

    • Processes that perform any form of computation.
    • Nodes can communicate with one another.
    • Example of nodes:
      • Publish sensor readings
      • Receiving teleop commands and running them
    • Written with ROS client libraries (rospy, roscpp)
  • Master (Primary) Node

    • Provides name registration, node lookup to all nodes in the computational graph.
    • Enables communication between nodes.
  • Parameter Server

    • “Distributed” key-value store: all nodes can access data stored in these keys.
  • Topics

    • Nodes communicating via the publish-subscribe semantics do so by publishing and subscribing to topics.
    • Every topic has a name, e.g. /sensors/temp1
    • No access permissions
  • Services

    • Request-response semantics (think Web servers)
    • Requests are blocking

Example Computational Graph

Getting Started With ROS

ROS Environment Setup

Here I assume you have the ROS environment set up. If not, see the appendix.

Creating a ROS Workspace

Catkin is ROS’ package manager, built on top of CMake.

mkdir -p ~/catkin_ws/src        # Create the directories
cd ~/catkin_ws/                 # Change to the directory
catkin_make                     # Initial setup

Exploring ROS shell commands 1

  • rospack

    rospack find locates ROS packages.

    rospack find roscpp # /opt/ros/melodic/share/roscpp
  • roscd

    roscd changes you to the directory of the ros package.

    roscd roscpp
    pwd # /opt/ros/melodic/share/roscpp

Creating a ROS package

We use the convenience script catkin_create_pkg to instantiate our package.

cd ~/catkin_ws/src
catkin_create_pkg workshop std_msgs rospy roscpp
# Created file workshop/CMakeLists.txt
# Created file workshop/package.xml
# Created folder workshop/include/workshop
# Created folder workshop/src
# Successfully created files in /home/jethro/catkin_ws/src/workshop. Please adjust the values in package.xml.

What’s in a ROS package?

    CMakeLists.txt          # Build instructions
    include                 # For cpp deps, if any
    package.xml             # Details about the package
    src                     # Contains source code

Starting ROS

We initialize the ROS master node with roscore.


# ...
# process[master]: started with pid [16206]
# ROS_MASTER_URI=http://jethro:11311/

# setting /run_id to 05bf8c5e-efed-11e9-957b-382c4a4f3d31
# process[rosout-1]: started with pid [16217]

To kill it, press Ctrl-C in the same terminal.

ROS Nodes

  • rosnode

    rosnode let’s us inspect available nodes:

    rosnode list                    # /rosout
    rosnode info /rosout

    What happens if master is not running?

    rosnode list               # ERROR: Unable to communicate with master!
  • Running a ROS node

    A ROS package may contain many ROS nodes.

    rosrun turtlesim <TAB>
    # draw_square        mimic              turtlesim_node     turtle_teleop_key
    rosrun turtlesim turtlesim_node
    # [ INFO] [1571214245.786246078]: Starting turtlesim with node name /turtlesim
    # [ INFO] [1571214245.790986159]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

    Exercise: reinspect the node list.

ROS Topics

Now we have a visual simulation of a turtle. How do we make it move?

rosrun turtesim turtle_teleop_key
  • What’s going on?

    • turtle_teleop_key advertises on a ROS topic, and publishes each keystroke:
    rostopic list
    rostopic echo /turtle1/cmd_vel
  • ROS Messages

    • ROS messages are pre-defined formats. They are binarized and compressed before they are sent over the wire.
    rostopic type /turtle1/cmd_vel   # geometry_msgs/Twist
  • Monitoring the Topic

    • The rate at which messages is published is good to monitor (in Hz).
    • A topic that has too many messages can get congested, and buffer/drop many messages, or congest the ROS network.
    rostopic hz /turtle1/cmd_vel
    # subscribed to [/turtle1/cmd_vel]
    # average rate: 13.933
    # min: 0.072s max: 0.072s std dev: 0.00000s window: 2
  • Rosbag

    • A bag is subscribes to one or more topics, and stores serialized data that is received (for logging/replay)
    rosbag record /turtle1/cmd_vel
    # [ INFO] [1571294982.145679913]: Subscribing to /turtle1/cmd_vel
    # [ INFO] [1571294982.168808833]: Recording to 2019-10-17-14-49-42.bag

ROS Services

  • Services allow request-response interactions between nodes.
rosservice list
rosservice call /clear
rosservice type /spawn | rossrv show

ROS Params

the rosparams commandline interface allows us to store and manipulate data on the ROS Parameter server. 2

rosparam set            # set parameter
rosparam get            # get parameter
rosparam load           # load parameters from file
rosparam dump           # dump parameters to file
rosparam delete         # delete parameter
rosparam list           # list parameter names

Pubsub <a id=“0eb03dca701c737878a6bf71343edd56” href=“#wiki_pubsub” title=“@misc{wiki_pubsub,

author = {nil}, howpublished = { \%28python \%29}, note = {Online; accessed 17 October 2019}, title = {ROS/Tutorials/WritingPublisherSubscriber(python) - ROS Wiki}, year = {nil}, }“>@misc{wiki_pubsub, author = {nil}, howpublished = { \%28python \%29}, note = {Online; accessed 17 October 2019}, title = {ROS/Tutorials/WritingPublisherSubscriber(python) - ROS Wiki}, year = {nil}, } {#pubsub-a-id-0eb03dca701c737878a6bf71343edd56-href-wiki-pubsub-title-misc-wiki-pubsub-author-nil-howpublished-http-wiki-dot-ros-dot-org-ros-tutorials-writingpublishersubscriber-28python-29-note-online-accessed-17-october-2019-title-ros-tutorials-writingpublishersubscriber–python–ros-wiki-year-nil-misc-wiki-pubsub-author-nil-howpublished-http-wiki-dot-ros-dot-org-ros-tutorials-writingpublishersubscriber-28python-29-note-online-accessed-17-october-2019-title-ros-tutorials-writingpublishersubscriber–python–ros-wiki-year-nil-a}

When do we use topics?

Previously we looked at ready-made ROS packages and how they used topics and services. Now, we’ll write our own publisher and subscriber.

The pubsub interface is useful in situations where a response for each request is not required:

  • Sensor readings
  • Log info

A Simple Publisher

We use rospy, but roscpp is fine as well. We create a new file in our workshop package workshop/src/

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

pub = rospy.Publisher('my_topic', String, queue_size=10) # initializes topic
rospy.init_node('talker', anonymous=True) # required to talk to Master

while not rospy.is_shutdown():

Executing the Publisher Node

We need to make our Python file executable:

chmod +x
rosrun workshop

Exercise: monitor the output. What’s wrong? (hint: Hz)

Setting the rate of publishing

We use the Rate object, and the rate.sleep() to set the rate of publishing:

rate = rospy.Rate(10)           # 10 hz
# ...
# ...

Good Practice

We often wrap all our logic in a function, and catch the ROSInterruptException exception:

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def talker():
    pub = rospy.Publisher('my_topic', String, queue_size=10) # initializes topic
    # ...

except rospy.ROSInterruptException:

Exercise: Write a time publisher (5 minutes)

Goal: publish the current date-time onto a topic /datetime.

Hint: Python has a datetime library.


We create a listener in workshop/src/

#!/usr/bin/env python
import rospy
from std_msg.msg import String

def echo(data):

def listener():
    rospy.init_node("listener", anonymous=True)
    rospy.Subscriber("my_topic", String, echo)
    rospy.spin() # prevents python from exiting



rospy.init_node(name)           # create node
rospy.Publisher(topic_name, msg_type) # create publisher
rospy.Subscriber(topic_name, msg_type, callback) # create subscriber
rospy.Rate(10)                  # rate object
rospy.spin()                    # spin

Services <a id=“d9f8b17a885ac23c956840df53cacd3f” href=“#wiki_service” title=“@misc{wiki_service,

author = {nil}, howpublished = { \%28python \%29}, note = {Online; accessed 17 October 2019}, title = {ROS/Tutorials/WritingServiceClient(python) - ROS Wiki}, year = {nil}, }“>@misc{wiki_service, author = {nil}, howpublished = { \%28python \%29}, note = {Online; accessed 17 October 2019}, title = {ROS/Tutorials/WritingServiceClient(python) - ROS Wiki}, year = {nil}, } {#services-a-id-d9f8b17a885ac23c956840df53cacd3f-href-wiki-service-title-misc-wiki-service-author-nil-howpublished-http-wiki-dot-ros-dot-org-ros-tutorials-writingserviceclient-28python-29-note-online-accessed-17-october-2019-title-ros-tutorials-writingserviceclient–python–ros-wiki-year-nil-misc-wiki-service-author-nil-howpublished-http-wiki-dot-ros-dot-org-ros-tutorials-writingserviceclient-28python-29-note-online-accessed-17-october-2019-title-ros-tutorials-writingserviceclient–python–ros-wiki-year-nil-a}

Msg and Srv

message files that define the format of a ROS message. These generate source code for different languages (think Apache Thrift, Protobuf).
describes a service (request/response)

Creating a msg

mkdir -p workshop/msg

Create a file workshop/msg/Num.msg:

int64 num

Compiling the msg

In package.xml:


In CMakeLists.txt:

find_package(catkin REQUIRED COMPONENTS

  CATKIN_DEPENDS message_runtime ...



Compile the message:

cd ~/catkin_ws
catkin_make install
# ...
# [100%] Built target workshop_generate_messages_cpp
# [100%] Built target workshop_generate_messages_py
# [100%] Built target workshop_generate_messages_eus
# Scanning dependencies of target workshop_generate_messages
# [100%] Built target workshop_generate_messages

Using the ROS msg

rosmsg list                     # ... workshop/Num
rosmsg show workshop/Num        # int64 num

Creating a ROS srv

mkdir -p workshop/srv

In workshop/srv/SumInts.srv:

int64 a
int64 b
int64 sum

Compiling the ROS srv

Since srv files are also compiled, the setup is similar to compiling msgs.

Writing a Service Node

We can create a server that uses the service file we defined earlier:

#!/usr/bin/env python
from workshop.srv import SumInts, SumIntsResponse
import rospy

def handler(req):
    return SumIntsResponse(req.a + req.b)

def sumints_server():
    s = rospy.Service("sumints", SumInts, handler)


Writing a Client

#!/usr/bin/env python
import sys
import rospy
from workshop.srv import SumInts

def sumints_client(x, y):
        sumints = rospy.ServiceProxy('sumints', SumInts)
        resp1 = sumints(x, y)
        return resp1.sum
    except rospy.ServiceException, e:
        print "Service call failed: %s"%e

x = int(sys.argv[1])
y = int(sys.argv[2])
print "%s + %s = %s"%(x, y, sumints_client(x, y))
rosrun workshop 1 2
# 1 + 2 = 3

Exercise: Time Service (15 minutes)

Write a service that:

  • requests nothing
  • responds with the current time

Write a client that sends the request and prints this response.

What’s Next?

What’s Next?

  • Run a simulator, model the robot using URDF
  • Look at community ROS packages
    • tf2: maintain robotic coordinate frames (pose estimation)
    • gmapping/slam etc.: navigation
  • Look at ROS 2


Common Pitfalls

  1. Not sourcing your devel/setup.bash:
source devel/setup.bash
  1. This is necessary to make available all the C++ and python ROS packages that you have built
  2. I recommend using direnv, and sourcing it every time you enter the Catkin workspace.

ROS Installation



nil, (nil). Ros/introduction - ros wiki. Retrieved from Online; accessed 15 October 2019.

nil, (nil). Ros/tutorials/writingpublishersubscriber(python) - ros wiki. Retrieved from \%28python \%29. Online; accessed 17 October 2019.

nil, (nil). Ros/tutorials/writingserviceclient(python) - ros wiki. Retrieved from \%28python \%29. Online; accessed 17 October 2019.

nil, (nil). Melodic/installation/ubuntu - ros wiki. Retrieved from Online; accessed 16 October 2019.

  1. Almost all these commands have tab completion! [return]
  2. can also be done programatically [return]

Icon by Laymik from The Noun Project. Website built with ♥ with Org-mode, Hugo, and Netlify.