Book Image

Mastering ROS for Robotics Programming

By : Lentin Joseph
Book Image

Mastering ROS for Robotics Programming

By: Lentin Joseph

Overview of this book

The area of robotics is gaining huge momentum among corporate people, researchers, hobbyists, and students. The major challenge in robotics is its controlling software. The Robot Operating System (ROS) is a modular software platform to develop generic robotic applications. This book discusses the advanced concepts in robotics and how to program using ROS. It starts with deep overview of the ROS framework, which will give you a clear idea of how ROS really works. During the course of the book, you will learn how to build models of complex robots, and simulate and interface the robot using the ROS MoveIt motion planning library and ROS navigation stacks. After discussing robot manipulation and navigation in robots, you will get to grips with the interfacing I/O boards, sensors, and actuators of ROS. One of the essential ingredients of robots are vision sensors, and an entire chapter is dedicated to the vision sensor, its interfacing in ROS, and its programming. You will discuss the hardware interfacing and simulation of complex robot to ROS and ROS Industrial (Package used for interfacing industrial robots). Finally, you will get to know the best practices to follow when programming using ROS.
Table of Contents (19 chapters)
Mastering ROS for Robotics Programming
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Understanding the ROS computation graph level


The computation in ROS is done using a network of process called ROS nodes. This computation network can be called the computation graph. The main concepts in the computation graph are ROS Nodes, Master, Parameter server, Messages, Topics, Services, and Bags. Each concept in the graph is contributed to this graph in different ways.

The ROS communication related packages including core client libraries such as roscpp and rospython and the implementation of concepts such as topics, nodes, parameters, and services are included in a stack called ros_comm (http://wiki.ros.org/ros_comm).

This stack also consists of tools such as rostopic, rosparam, rosservice, and rosnode to introspect the preceding concepts.

The ros_comm stack contains the ROS communication middleware packages and these packages are collectively called ROS Graph layer.

Figure 6 : Structure of the ROS Graph layer

The following are abstracts of each graph's concepts:

  • Nodes: Nodes are the process that perform computation. Each ROS node is written using ROS client libraries such as roscpp and rospy. Using client library APIs, we can implement different types of communication methods in ROS nodes. In a robot, there will be many nodes to perform different kinds of tasks. Using the ROS communication methods, it can communicate with each other and exchange data. One of the aims of ROS nodes is to build simple processes rather than a large process with all functionality. Being a simple structure, ROS nodes are easy to debug too.

  • Master: The ROS Master provides name registration and lookup to the rest of the nodes. Nodes will not be able to find each other, exchange messages, or invoke services without a ROS Master. In a distributed system, we should run the master on one computer, and other remote nodes can find each other by communicating with this master.

  • Parameter Server: The parameter server allows you to keep the data to be stored in a central location. All nodes can access and modify these values. Parameter server is a part of ROS Master

  • Messages: Nodes communicate with each other using messages. Messages are simply a data structure containing the typed field, which can hold a set of data and that can be sent to another node. There are standard primitive types (integer, floating point, Boolean, and so on) and these are supported by ROS messages. We can also build our own message types using these standard types.

  • Topics: Each message in ROS is transported using named buses called topics. When a node sends a message through a topic, then we can say the node is publishing a topic. When a node receives a message through a topic, then we can say that the node is subscribing to a topic. The publishing node and subscribing node are not aware of each other's existence. We can even subscribe a topic that might not have any publisher. In short, the production of information and consumption of it are decoupled. Each topic has a unique name, and any node can access this topic and send data through it as long as they have the right message type.

  • Services: In some robot applications, a publish/subscribe model will not be enough if it needs a request/response interaction. The publish/subscribe model is a kind of one-way transport system and when we work with a distributed system, we might need a request/response kind of interaction. ROS Services are used in these case. We can define a service definition that contains two parts; one is for requests and the other is for responses. Using ROS Services, we can write a server node and client node. The server node provides the service under a name, and when the client node sends a request message to this server, it will respond and send the result to the client. The client might need to wait until the server responds. The ROS service interaction is like a remote procedure call.

  • Bags: Bags are a format for saving and playing back ROS message data. Bags are an important mechanism for storing data, such as sensor data, which can be difficult to collect but is necessary for developing and testing robot algorithms. Bags are very useful features when we work with complex robot mechanisms.

The following graph shows how the nodes communicate with each other using topics. The topics are mentioned in a rectangle and nodes are represented in ellipses. The messages and parameters are not included in this graph. These kinds of graphs can be generated using a tool called rqt_graph (http://wiki.ros.org/rqt_graph).

Figure 7 : Graph of communication between nodes using topics

Understanding ROS nodes

ROS nodes are a process that perform computation using ROS client libraries such as roscpp and rospy. One node can communicate with other nodes using ROS Topics, Services, and Parameters.

A robot might contain many nodes, for example, one node processes camera images, one node handles serial data from the robot, one node can be used to compute odometry, and so on.

Using nodes can make the system fault tolerant. Even if a node crashes, an entire robot system can still work. Nodes also reduce the complexity and increase debug-ability compared to monolithic codes because each node is handling only a single function.

All running nodes should have a name assigned to identify them from the rest of the system. For example, /camera_node could be a name of a node that is broadcasting camera images.

There is a rosbash tool to introspect ROS nodes. The rosnode command can be used to get information about a ROS node. Here are the usages of rosnode:

  • $ rosnode info [node_name]: This will print the information about the node

  • $ rosnode kill [node_name]: This will kill a running node

  • $ rosnode list: This will list the running nodes

  • $ rosnode machine [machine_name]: This will list the nodes running on a particular machine or a list of machines

  • $ rosnode ping: This will check the connectivity of a node

  • $ rosnode cleanup: This will purge the registration of unreachable nodes

We will see example nodes using the roscpp client and will discuss the working of ROS nodes that use functionalities such ROS Topics, Service, Messages, and actionlib.

ROS messages

ROS nodes communicate with each other by publishing messages to a topic. As we discussed earlier, messages are a simple data structure containing field types. The ROS message supports standard primitive datatypes and arrays of primitive types.

Nodes can also exchange information using service calls. Services are also messages, the service message definitions are defined inside the srv file.

We can access the message definition using the following method. For example, to access std_msgs/msg/String.msg, we can use std_msgs/String. If we are using the roscpp client, we have to include std_msgs/String.h for the string message definition.

In addition to message data type, ROS uses an MD5 checksum comparison to confirm whether the publisher and subscriber exchange the same message data types.

ROS has inbuilt tools called rosmsg to get information about ROS messages. Here are some parameters used along with rosmsg:

  • $ rosmsg show [message]: This shows the message description

  • $ rosmsg list: This lists all messages

  • $ rosmsg md5 [message]: This displays md5sum of a message

  • $ rosmsg package [package_name]: This lists messages in a package

  • $ rosmsg packages [package_1] [package_2]: This lists packages that contain messages

ROS topics

ROS topics are named buses in which ROS nodes exchange messages. Topics can anonymously publish and subscribe, which means that the production of messages is decoupled from the consumption. The ROS nodes are not interested to know which node is publishing the topic or subscribing topics, it only looks for the topic name and whether the message types of publisher and subscriber are matching.

The communication using topics are unidirectional, if we want to implement request/response such as communication, we have to switch to ROS services.

The ROS nodes communicate with topics using TCP/IP-based transport known as TCPROS. This method is the default transport method used in ROS. Another type of communication is UDPROS, which has low-latency, loose transport, and is only suited for teleoperation.

The ROS topic tool can be used to get information about ROS topics. Here is the syntax of this command:

  • $ rostopic bw /topic: This command will display the bandwidth used by the given topic

  • $ rostopic echo /topic: This command will print the content of the given topic

  • $ rostopic find /message_type: This command will find topics using the given message type

  • $ rostopic hz /topic: This command will display the publishing rate of the given topic

  • $ rostopic info /topic: This command will print information about an active topic

  • $ rostopic list: This command will list all active topics in the ROS system

  • $ rostopic pub /topic message_type args: This command can be used to publish a value to a topic with a message type

  • $ rostopic type /topic: This will display the message type of the given topic

ROS services

When we need a request/response kind of communication in ROS, we have to use the ROS services. ROS topics can't do this kind of communication because it is unidirectional. ROS services are mainly used in a distributed system.

The ROS services is defined using a pair of messages. We have to define a request datatype and a response datatype in a srv file. The srv files are kept in a srv folder inside a package.

In ROS services, one node acts as a ROS server in which the service client can request the service from the server. If the server completes the service routine, it will send the results to the service client.

The ROS service definition can be accessed by the following method, for example, if my_package/srv/Image.srv can be accessed by my_package/Image.

In ROS services also, there is an MD5 checksum that checks in the nodes. If the sum is equal, then only the server responds to the client.

There are two ROS tools to get information about the ROS service. The first tool is rossrv, which is similar to rosmsg, and is used to get information about service types. The next command is rosservice, which is used to list and query about the running ROS services.

The following explain how to use the rosservice tool to get information about the running services:

  • $ rosservice call /service args: This tool will call the service using the given arguments

  • $ rosservice find service_type: This command will find services in the given service type

  • $ rosservice info /services: This will print information about the given service

  • $ rosservice list: This command will list the active services running on the system

  • $ rosservice type /service: This command will print the service type of a given service

  • $ rosservice uri /service: This tool will print the service ROSRPC URI

ROS bags

A bag file in ROS is for storing ROS message data from topics and services. The .bag extension is used to represent a bag file.

Bag files are created using the rosbag command, which will subscribe one or more topics and store the message's data in a file as it's received. This file can play the same topics as they are recorded from or it can remap the existing topics too.

The main application of rosbag is data logging. The robot data can be logged and can visualize and process offline.

The rosbag command is used to work with rosbag files. Here are the commands to record and playback a bag file:

  • $ rosbag record [topic_1] [topic_2] -o [bag_name]: This command will record the given topics into a bag file that is given in the command. We can also record all topics using the -a argument.

  • $ rosbag play [bag_name]: This will playback the existing bag file.

Here are more details about this command:

http://wiki.ros.org/rosbag/Commandline

There is a GUI tool to handle record and playback of bag files called rqt_bag. Go to the following link to know more about rqt_bag:

http://wiki.ros.org/rqt_bag

Understanding ROS Master

ROS Master is much like a DNS server. When any node starts in the ROS system, it will start looking for ROS Master and register the name of the node in it. So ROS Master has the details of all nodes currently running on the ROS system. When any details of the nodes change, it will generate a call-back and update with the latest details. These node details are useful for connecting with each node.

When a node starts publishing a topic, the node will give the details of the topic such as name and data type to ROS Master. ROS Master will check whether any other nodes are subscribed to the same topic. If any nodes are subscribed to the same topic, ROS Master will share the node details of the publisher to the subscriber node. After getting the node details, these two nodes will interconnect using the TCPROS protocol, which is based on TCP/IP sockets. After connecting to the two nodes, ROS Master has no role in controlling them. We might be able to stop either the publisher node or the subscriber node according to our wish. If we stop any nodes, it will check with ROS Master once again. This same method is for the ROS services.

The nodes are written using the ROS client libraries such as roscpp and rospy. These clients interact with ROS Master using XMLRPC (XML Remote Procedure Call) based APIs, which act as the backend of the ROS system APIs.

The ROS_MASTER_URI environment variable contains the IP and port of ROS Master. Using this variable, ROS nodes can locate ROS Master. If this variable is wrong, the communication between nodes will not take place. When we use ROS in a single system, we can use the IP of localhost or the name localhost itself. But in a distributed network, in which computation is on different physical computers, we should define ROS_MASTER_URI properly, only then, the remote node could find each other and communicate with each other. We need only one Master, in a distributed system, and it should run on a computer in which all other computers can ping it properly to ensure that remote ROS nodes can access the Master.

The following diagram shows an illustration of how ROS Master interacts with a publishing and subscribing node, the publisher node publishing a string type topic with a "Hello World" message and the subscriber node subscribes to this topic.

Figure 8: Communication between ROS Master and Hello World publisher and subscriber

When the publisher node starts publishing the "Hello World" message in a particular topic, ROS Master gets the details of the topic and details of the node. It will search whether any node is subscribing the same topic. If there are no nodes subscribing the same topic at that time, both nodes remain unconnected. If the publisher and subscriber nodes run at the same time, ROS Master exchanges the details of the publisher to the subscriber and they will connect and can exchange data through ROS messages.

Using the ROS parameter

While programming a robot, we might have to define robot parameters such as robot controller gain such as P, I, and D. When the number of parameters increases, we might need to store it as files. In some situation, these parameters have to share between two or more programs too. In this case, ROS provides a parameter server, which is a shared server in which all ROS nodes can access parameters from this server. A node can read, write, modify and delete parameter values from the parameter server.

We can store these parameters in a file and load them into the server. The server can store a wide variety of data types and can even store dictionaries. The programmer can also set the scope of the parameter, that is, whether it can be accessed by only this node or all the nodes.

The parameter server supports the following XMLRPC datatypes, which include:

  • 32-bit integers

  • Booleans

  • strings

  • doubles

  • iso8601 dates

  • lists

  • base64-encoded binary data

We can also store dictionaries on the parameter server. If the number of parameters is high, we can use a YAML file to save it. Here is an example of the YAML file parameter definitions:

/camera/name : 'nikon'   #string type
/camera/fps : 30         #integer    
/camera/exposure : 1.2   #float 
/camera/active : true    #boolean

The rosparam tool used to get and set the ROS parameter from the command line. The following are the commands to work with ROS parameters:

  • $ rosparam set [parameter_name] [value]: This command will set a value in the given parameter

  • $ rosparam get [parameter_name]: This command will retrieve a value from the given parameter

  • $ rosparam load [YAML file]: The ROS parameters can be saved into a YAML file and it can load to the parameter server using this command

  • $ rosparam dump [YAML file]: This command will dump the existing ROS parameters to a YAML file

  • $ rosparam delete [parameter_name]: This command will delete the given parameter

  • $ rosparam list: This command will list existing parameter names

The parameters can be changed dynamically during the execution of the node that uses these parameters, using the dyamic_reconfigure package (http://wiki.ros.org/dynamic_reconfigure).