Book Image

Mastering ROS for Robotics Programming - Second Edition

By : Jonathan Cacace, Lentin Joseph
Book Image

Mastering ROS for Robotics Programming - Second Edition

By: Jonathan Cacace, Lentin Joseph

Overview of this book

In this day and age, robotics has been gaining a lot of traction in various industries where consistency and perfection matter. Automation is achieved via robotic applications and various platforms that support robotics. The Robot Operating System (ROS) is a modular software platform to develop generic robotic applications. This book focuses on the most stable release of ROS (Kinetic Kame), discusses advanced concepts, and effectively teaches you programming using ROS. We begin with aninformative overview of the ROS framework, which will give you a clear idea of how ROS works. During the course of this book, you’ll learn to build models of complex robots, and simulate and interface the robot using the ROS MoveIt! motion planning library and ROS navigation stacks. Learn to leverage several ROS packages to embrace your robot models. After covering robot manipulation and navigation, you’ll get to grips with the interfacing I/O boards, sensors, and actuators of ROS. Vision sensors are a key component of robots, and an entire chapter is dedicated to the vision sensor and image elaboration, its interface in ROS and programming. You’ll also understand the hardware interface and simulation of complex robots to ROS and ROS Industrial. At the end of this book, you’ll discover the best practices to follow when programming using ROS.
Table of Contents (22 chapters)
Title Page
Copyright and Credits
www.PacktPub.com
Contributors
Preface
Index

Understanding the ROS computation graph level


The computation in ROS is done using a network of a 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 the 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. Using client library APIs, we can implement different ROS functionalities, such as the communication methods between nodes, which is particularly useful when different nodes of our robot must exchange information between them. Using the ROS communication methods, they 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 the functionality. Being a simple structure, ROS nodes are easy to debug.
  • Master: The ROS Master provides the 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. The parameter server is a part of the 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, the publish/subscribe communication model may not be suitable. For example, in some cases, we need a kind of request/response interaction, in which one node can ask for the execution of a fast  procedure to another node; for example, asking for some quick calculation. The ROS service interaction is like a remote procedure call.
  • Logging: ROS provides a logging system for storing data, such as sensor data, which can be difficult to collect but is necessary for developing and testing robot algorithms: the bagfiles. Bagfiles 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 the 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

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 code 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 look at 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 in knowing which node is publishing the topic or subscribing topics; they only look for the topic name and whether the message types of the publisher and subscriber are matching.

The communication using topics are unidirectional. If we want to implement a 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 teleoperations.

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 in a human readable format. Users can use the "-p" option to print data in a csv format.
  • $ 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 implement natively such kind of communication because it is unidirectional. The ROS services are mainly used in a distributed system.

The ROS services are 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. For example, consider a node able to provide the sum of two numbers received in input, implementing this functionality through a ROS service. The other nodes of our system might request the sum of two numbers via this service. Differently, topics are used to stream continuous data flow.

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.

Further details about this command can be found at: http://wiki.ros.org/rosbag/Commandline

There is a GUI tool to handle the record and playback of bag files called rqt_bag. To learn more about rqt_bag, go to: http://wiki.ros.org/rqt_bag.

The ROS Master

The ROS Master is much like a DNS server, associating unique names and IDs to ROS elements active in our system. When any node starts in the ROS system, it will start looking for the ROS Master and register the name of the node in it. So, the ROS Master has the details of all the nodes currently running on the ROS system. When any details of the nodes change, it will generate a callback 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 the ROS Master. The ROS Master will check whether any other nodes are subscribed to the same topic. If any nodes are subscribed to the same topic, the 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, the 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 requirement. If we stop any nodes, it will check with the ROS Master once again. This same method is used for the ROS services.

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

The ROS_MASTER_URI environment variable contains the IP and port of the ROS Master. Using this variable, ROS nodes can locate the 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 a 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 will the remote nodes be able 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 the ROS Master interacts with a publishing and subscribing node, with the publisher node publishing a string type topic with a Hello World message and the subscriber node subscribing to this topic:

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

When the publisher node starts publishing the Hello World message in a particular topic, the ROS Master gets the details of the topic and details of the node. It will search whether any node is subscribing to the same topic. If there are no nodes subscribing to the same topic at that time, both nodes remain unconnected. If the publisher and subscriber nodes run at the same time, the 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

When programming a robot, we might have to define robot parameters, such as robot controller gains P, I, and D. When the number of parameters increases, we might need to store them as files. In some situations, 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:

  • 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 them. 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 is 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).