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 = {http://wiki.ros.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.ros.org/ROS/Introduction}, 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}

Why use ROS?

ROS Concepts

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

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?

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

Starting ROS

We initialize the ROS master node with roscore.

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

ROS Topics

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

rosrun turtesim turtle_teleop_key

ROS Services

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 = {http://wiki.ros.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.ros.org/ROS/Tutorials/WritingPublisherSubscriber \%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:

A Simple Publisher

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

#!/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():
    pub.publish("Hello")

Executing the Publisher Node

We need to make our Python file executable:

chmod +x talker.py
rosrun workshop talker.py

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
# ...
rate.sleep()
# ...

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
    # ...

try:
    talker()
except rospy.ROSInterruptException:
    pass

Exercise: Write a time publisher (5 minutes)

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

Hint: Python has a datetime library.

Subscriber

We create a listener in workshop/src/listener.py

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

def echo(data):
    print(data.data)

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

listener()

Summary

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 = {http://wiki.ros.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.ros.org/ROS/Tutorials/WritingServiceClient \%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

msg
message files that define the format of a ROS message. These generate source code for different languages (think Apache Thrift, Protobuf).
srv
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:

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

In CMakeLists.txt:

find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   std_msgs
   message_generation
)

catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
  ...)

add_message_files(
  FILES
  Num.msg
)

generate_messages()

Compile the message:

cd ~/catkin_ws
catkin_make
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():
    rospy.init_node("sumints_server")
    s = rospy.Service("sumints", SumInts, handler)
    rospy.spin()

sumints_server()

Writing a Client

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

def sumints_client(x, y):
    rospy.wait_for_service('sumints')
    try:
        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 sumint_client.py 1 2
# 1 + 2 = 3

Exercise: Time Service (15 minutes)

Write a service that:

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

What’s Next?

What’s Next?

Appendix

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

References

Bibliography

nil, (nil). Ros/introduction - ros wiki. Retrieved from http://wiki.ros.org/ROS/Introduction. Online; accessed 15 October 2019.

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

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

nil, (nil). Melodic/installation/ubuntu - ros wiki. Retrieved from http://wiki.ros.org/melodic/Installation/Ubuntu. Online; accessed 16 October 2019.


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