The main aim of this book is to teach you how to build an autonomous mobile robot from scratch. The robot will be programmed using ROS and its operations will be simulated using a simulator called Gazebo. You will also see the robot's mechanical design, circuit design, embedded programming, and high-level software programming using ROS in the upcoming chapters.
In this chapter, we will start with the basics of ROS, how to install it, how to write a basic application using ROS and Python, and the basics of Gazebo. This chapter will be the foundation of your autonomous robotics project. If you are already aware of the basics of ROS, and already have it installed on your system, you may skip this chapter. However, you can still go through this chapter later to refresh your memory as to the basics of ROS.
This chapter will cover the following topics:
- Introduction to ROS
- Installing ROS Kinetic on Ubuntu 16.04.3
- Introducing, installing, and testing Gazebo
Let's start programming robots using Python and Robot Operating System (ROS).
To get the complete code that is mentioned in this chapter, you can clone the following link:
ROS is a software framework used for creating robotic applications. The main aim of the ROS framework is to provide the capabilities that you can use to create powerful robotics applications that can be reused for other robots. ROS has a collection of software tools, libraries, and collection of packages that makes robot software development easy.
ROS is a complete open source project licensed under the BSD (https://opensource.org/licenses/BSD-3-Clause) license. We can use it for research and commercial applications. Even though ROS stands for Robot Operating System, it is not a real operating system. Rather, it is a meta-operating system, which provides the features of a real operating system. Here are the major features that ROS provides:
- Message passing interface: This is the core feature of ROS, and it enables interprocess communication. Using this message-passing capability, the ROS program can communicate with its linked systems and exchange data. We will learn more technical terms concerning the exchange of data between ROS programs/nodes in the coming sections and chapters.
- Hardware abstraction: ROS has a degree of abstraction that enables developers to create robot-agnostic applications. These kinds of application can be used with any robot; the developers need only worry about the underlying robot hardware.
- Package management: The ROS nodes are organized in packages called ROS packages. ROS packages consist of source codes, configuration files, build files, and so on. We create the package, build the package, and install the package. There is a build system in ROS that helps to build these packages. The package management in ROS makes ROS development more systematic and organized.
- Third-party library integration: The ROS framework is integrated with many third-party libraries, such as Open-CV, PCL, OpenNI, and so on. This helps developers to create all kinds of application in ROS.
- Low-level device control: When we work with robots, we may need to work with low-level devices, such as those that control I/O pins, sending data through serial ports, and so on. This can also be done using ROS.
- Distributed computing: The amount of computation required to process the data from robot sensors is very high. Using ROS, we can easily distribute the computation to a cluster of computing nodes. This distributes the computing power and allows you to process the data faster than you could using a single computer.
- Code reuse: The main goal of ROS is code reuse. Code reuse enables the growth of a good research and development community around the world. ROS executables are called nodes. These executables can be grouped into a single entity called a ROS package. A group of packages is called a meta package, and both packages and meta packages can be shared and distributed.
- Language independence: The ROS framework can be programmed using popular languages (such as Python, C++, and Lisp). The nodes can be written in any language and can communicate through ROS without any issues.
- Easy testing: ROS has a built-in unit/integration test framework called rostest to test ROS packages.
- Scaling: ROS can be scaled to perform complex computation in robots.
- Free and open source: The source code of ROS is open and it's absolutely free to use. The core part of ROS is licensed under a BSD license, and it can be reused in commercial and closed source products.
ROS is a combination of plumbing (message passing), tools, capabilities, and ecosystem. There are powerful tools in ROS to debug and visualize the robot data. There are inbuilt robot capabilities in ROS, such as robot navigation, localization, mapping, manipulation, and so on. They help to create powerful robotics applications.
The following image shows the ROS equation:
There are three main organizational levels in ROS:
- The ROS filesystem
- The ROS computation graph
- The ROS community
The ROS filesystem mainly covers how ROS files are organized on the disk. The following are the main terms that we have to understand when working with the ROS filesystem:
- Packages: ROS packages are the individual unit of the ROS software framework. A ROS package may contain source code, third-party libraries, configuration files, and so on. ROS packages can be reused and shared.
- Package manifests: The manifests (package.xml) file will have all the details of the packages, including the name, description, license, and, more importantly, the dependencies of the package.
- Message (msg) types: Message descriptions are stored in the msg folder in a package. ROS messages are data structures for sending data through ROS's message-passing system. Message definitions are stored in a file with the .msg extension.
- Service (srv) types: Service descriptions are stored in the srv folder with the .srv extension. The srv file defines the request and response data structure for the service in ROS.
The ROS Computation Graph is the peer-to-peer network of ROS systems that processes data. The basic features of ROS Computation Graph are nodes, ROS Master, the parameter server, messages, and services:
- Nodes: The ROS node is a process that uses ROS functionalities to process the data. A node basically computes. For example, a node can process the laser scanner data to check whether there is any collision. A ROS node is written with the help of an ROS client library (such as roscpp and rospy), which will be discussed in the upcoming section.
- ROS Master: The ROS nodes can connect to each other using a program called ROS Master. This provides the name, registration, and lookup to the rest of the computation graph. Without starting the master, the nodes will not find each other and send messages.
- Parameter server: The ROS parameters are static values that are stored in a global location called the parameter server. From the parameter server, all the nodes can access these values. We can even set the scope of the parameter server as private or public so that it can access one node or access all nodes.
- ROS topics: The ROS nodes communicate with each other using a named bus called ROS topic. The data flows through the topic in the form of messages. The sending of messages over a topic is called publishing, and receiving the data through a topic is called subscribing.
- Messages: A ROS message is a data type that can consist of primitive data types, such as integers, floating points, and Booleans. The ROS messages flow through the ROS topic. A topic can only send/receive one type of message at a time. We can create our own message definition and send it through the topics.
- Services: We have seen that the publish/subscribe model using ROS topics is a very easy way of communicating. This communication method is a one-to-many mode of communication, meaning that a topic can be subscribed to by any number of nodes. In some cases, we may also require a request/reply kind of interaction, which is usually used in distributed systems. This kind of interaction can be done using ROS services. The ROS services work in a similar way to ROS topics in that they have a message type definition. Using that message definition, we can send the service request to another node that provides the service. The result of the service will be sent as a reply. The node has to wait until the result is received from the other node.
- Bags: These are formats in which to save and play back the ROS topics. ROS bags are an important tool to log the sensor data and the processed data. These bags can be used later for testing our algorithm offline.
The following diagram shows how topics and services work between the nodes and the Master:
In the preceding diagram, you can see two ROS nodes with the ROS Master in between them. One thing we have to remember is, before starting any nodes in ROS, you should start the ROS Master. The ROS Master acts like a mediator between nodes for exchanging information about other ROS nodes in order to establish communication. Say that Node 1 wants to publish a topic called /xyz with message type abc. It will first approach the ROS Master, and says I am going to publish a topic called /xyz with message type abc and share its details. When another node, say Node 2, wants to subscribe to the same topic of /xyz with the message type of abc, the Master will share the information about Node 1 and allocate a port to start communication between these two nodes directly without communicating with the ROS Master.
The ROS services works in the same way. The ROS Master is a kind of DNS server, which can share the node details when the second node requests a topic or service from the first node. The communication protocol ROS uses is TCPROS (http://wiki.ros.org/ROS/TCPROS), which basically uses TCP/IP sockets for the communication.
The ROS community consists of ROS developers and researchers who can create and maintain packages and exchange new information related to existing packages, newly released packages, and other news related to the ROS framework. The ROS community provides the following services:
- Distributions: A ROS distribution has a set of packages that come with a specific version. The distribution that we are using in this book is ROS Kinetic. There are other versions available, such as ROS Lunar and Indigo, which has a specific version that we can install. It is easier to maintain the packages in each distribution. In most cases, the packages inside a distribution will be relatively stable.
- Repositories: The online repositories are the locations where we keep our packages. Normally, developers keep a set of similar packages called meta packages in a repository. We can also keep an individual package in a single repository. We can simply clone these repositories and build or reuse the packages.
- The ROS wiki: The ROS wiki is the place where almost all the documentation of ROS is available. You can learn about ROS, from its most basic concepts to the most advanced programming, using the ROS wiki (http://wiki.ros.org).
- Mailing lists: If you want to get updates regarding ROS, you can subscribe to the ROS mailing list (http://lists.ros.org/mailman/listinfo/ros-users). You can also get the latest ROS news from ROS Discourse (https://discourse.ros.org).
- ROS answers: This is very similar to the Stack Overflow website. You can ask questions related to ROS in this portal, and you might get support from developers across the world (https://answers.ros.org/questions/).
There are many other features available in ROS; you can refer to the ROS official website at www.ros.org for more information. For now, we will move on to the installation procedure of ROS.
As per our previous discussion, we know that ROS is a metaoperating system that is installed on a host system. ROS is completely supported on Ubuntu /Linux and in the experimental stages on Windows and OS X. Some of the latest ROS distributions are as follows:
ROS Melodic Morenia
May 23 2018
ROS Lunar Loggerhead
May 23 2017
ROS Kinetic Kame
May 23 2016
ROS Indigo Igloo
July 22 2014
We will now look at the installation procedure of the stable, long-term support (LTS) distribution of ROS called Kinetic on Ubuntu 16.04.3 LTS. ROS Kinetic Kame will be primarily targeted at Ubuntu 16.04 LTS. You can also find instructions to set up ROS in the latest LTS Melodic Morenia on Ubuntu 18.04 LTS after looking at the following instructions. If you are a Windows or OS X user, you can install Ubuntu in a VirtualBox application before installing ROS on it. The link to download VirtualBox is https://www.virtualbox.org/wiki/Downloads.
You can find the complete instructions for doing this at http://wiki.ros.org/kinetic/Installation/Ubuntu.
The steps are as follows:
- Configure your Ubuntu repositories to allow restricted, universe, and multiverse downloadable files. We can configure it using Ubuntu's Software & Update tool. We can get this tool by simply searching on the Ubuntu Unity search menu and ticking the shown in the following screenshot:
- Set up your system to accept ROS packages from packages.ros.org. ROS Kinetic is supported only on Ubuntu 15.10 and 16.04. The following command will store packages.ros.org in Ubuntu's apt repository list:
$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
- Next, we have to add apt-keys. An apt-key is used to manage the list of keys used by apt to authenticate the packages. Packages that have been authenticated using these keys will be considered trusted. The following command will add apt-keys for the ROS packages:
sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
- After adding the apt-keys, we have to update the Ubuntu package list. The following command will add and update the ROS packages, along with the Ubuntu packages:
$ sudo apt-get update
- After updating the ROS packages, we can install the packages. The following command will install all the necessary packages, tools, and libraries of ROS:
$ sudo apt-get install ros-kinetic-desktop-full
- We may need to install additional packages even after the desktop full installation. Each additional installation will be mentioned in the appropriate section. The desktop full install will take some time. After the installation of ROS, you will almost be done. The next step is to initialize rosdep, which enables you to easily install the system dependencies for ROS source packages:
$ sudo rosdep init
$ rosdep update
- To access ROS's tools and commands on the current bash shell, we can add ROS environmental variables to the .bashrc file. This will execute at the beginning of each bash session. The following is a command to add the ROS variable to .bashrc:
echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
The following command will execute the .bashrc script on the current shell to generate the change in the current shell:
- A useful tool to install the dependency of a package is rosinstall. This tool has to be installed separately. It enables you to easily download many source trees for the ROS package with one command:
$ sudo apt-get install python-rosinstall python-rosinstall-generator python-wstool build-essential
After the installation of ROS, we will discuss how to create a sample package in ROS. Before creating the package, we have to create a ROS workspace. The packages are created in the ROS workspace. We will use the catkin build system, which is a set of tools that is used to build packages in ROS. The catkin build system generates an executable or shared library from the source code. ROS Kinetic uses the catkin build system to build packages. Let's look at what catkin is.
Catkin is the official build system of ROS. Before catkin, ROS used the rosbuild system to build packages. Its replacement is catkin on the latest ROS version. Catkin combines CMake macros and Python scripts to provide the same normal workflow that CMake produces. Catkin provides better distribution of packages, better cross-compilation, and better portability than the rosbuild system. For more information, refer to wiki.ros.org/catkin.
Catkin workspace is a folder where you can modify, build, and install catkin packages.
Let's check how to create an ROS catkin workspace.
The following command will create a parent directory called catkin_ws and a subfolder called src:
$ mkdir -p ~/catkin_ws/src
Switch directory to the src folder using the following command. We will create our packages in the src folder:
$ cd ~/catkin_ws/src
Initialize the catkin workspace using the following command:
After you initialize the catkin workspace, you can simply build the package (even if there is no source file) using the following command:
$ cd ~/catkin_ws/ $ catkin_make
The catkin_make command is used to build packages inside the src directory. After building the packages, we will see a build and devel folder in catkin_ws The executables are stored in the build folder. In the devel folder, there are shell script files to add the workspace on the ROS environment.
In this section, we will look at how to create a sample package that contains two Python nodes. One of the nodes is used to publish a Hello World string message on a topic called /hello_pub and the other node will subscribe to this topic.
A catkin ROS package can be created using the catkin_create_pkg command in ROS.
The package is created inside the src folder that we created during the creation of the workspace. Before creating the packages, switch to the src folder using the following command:
$ cd ~/catkin_ws/src
The following command will create a hello_world package with std_msgs dependencies, which contain standard message definitions. The rospy is the Python client library for ROS:
$ catkin_create_pkg hello_world std_msgs rospy
This is the message we get upon a successful creation:
Created file hello_world/package.xml Created file hello_world/CMakeLists.txt Created folder hello_world/src Successfully created files in /home/lentin/catkin_ws/src/hello_world.
Please adjust the values in package.xml.
After the successful creation of the hello_world package, we need to add two Python nodes or scripts to demonstrate the subscribing and publishing of topics.
First, create a folder named scripts in the hello_world package using the following command:
$ mkdir scripts
Switch to the scripts folder and create a script named hello_world_publisher.py and another script called hello_world_subscriber.py to publish and subscribe to the hello world message. The following section covers the code and function of these scripts or nodes:
The hello_world_publisher.py node basically publishes a greeting message called hello world to a topic called /hello_pub. The greeting message is published to the topic at a rate of 10 Hz.
Here is a diagram that shows how the interaction between the two ROS nodes works:
The step-by-step explanation of how this code works is as follows:
- We need to import rospy if we are writing a ROS Python node. It contains Python APIs to interact with ROS topics, services, and so on.
- To send the hello world message, we have to import a String message data type from the std_msgs package. The std_msgs package has the message definition for standard data types. We can import using the following lines of code:
#!/usr/bin/env python import rospy from std_msgs.msg import String
- The following line of code creates a publisher object to a topic called hello_pub. The message type is String and the queue_size value is 10. If the subscriber is not fast enough to receive the data, we can use the queue_size option to buffer it:
def talker(): pub = rospy.Publisher('hello_pub', String, queue_size=10)
- The following line of code initializes a ROS node. It will also assign a name to the node. If two nodes are running with the same node name, one will shut down. If we want to run both, use anonymous=True flag as shown in the following code:
- The following line creates a rate object called r. Using a sleep() method in the Rate object, we can update the loop at the desired rate. Here, we are giving the rate the value of 10:
r = rospy.Rate(10) # 10hz
- The following loop will check whether rospy constructs the rospy.is_shutdown() flag. Then, it executes the loop. If we click on Ctrl + C, this loop will exit.
Inside the loop, a hello world message is printed on the Terminal and published on the hello_pub topic with a rate of 10 Hz:
while not rospy.is_shutdown(): str = "hello world %s"%rospy.get_time() rospy.loginfo(str) pub.publish(str) r.sleep()
- The following code has Python __main__ check and calls the talker() function. The code will keep on executing the talker(), and when Ctrl + C is pressed the node will get shut down:
if __name__ == '__main__': try: talker() except rospy.ROSInterruptException: pass
After publishing the topic, we will see how to subscribe to it. The following section covers the code needed to subscribe to the hello_pub topic.
The subscriber code is as follows:
#!/usr/bin/env python import rospy from std_msgs.msg import String
The following code is a callback function that is executed when a message reaches the hello_pub topic. The data variable contains the message from the topic, and it will print using rospy.loginfo():
def callback(data): rospy.loginfo(rospy.get_caller_id()+"I heard %s",data.data)
The following steps will start the node with a hello_world_subscriber name and start subscribing to the /hello_pub topic:
- The data type of the message is String, and when a message arrives on this topic, a method called callback will be called:
def listener(): rospy.init_node('hello_world_subscriber',
anonymous=True) rospy.Subscriber("hello_pub", String, callback)
- The following code will keep your node from exiting until the node is shut down:
- The following is the main section of the Python code. The main section will call the listener() method, which will subscribe to the /hello_pub topic:
if __name__ == '__main__': listener()
- After saving two Python nodes, you need to change the permission to executable using the chmod commands:
chmod +x hello_world_publisher.py chmod +x hello_world_subscriber.py
- After changing the file permission, build the package using the catkin_make command:
cd ~/catkin_ws catkin_make
- The following command adds the current ROS workspace path in all terminals so that we can access the ROS packages inside this workspace:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc
The following is the output of the subscriber and publisher nodes:
- First, we need to run roscore before starting the nodes. The roscore command or ROS master is needed to communicate between nodes. So, the first command is as follows:
- After executing roscore, run each node using the following commands:
- The following command will run the publisher:
$ rosrun hello_world hello_world_publisher.py
- The following command will run the subscriber node. This node subscribes to the hello_pub topic, as shown in the following code:
$ rosrun hello_world hello_world_subscriber.py
We have covered some of the basics of ROS. Now, we will see what Gazebo is and how we can work with Gazebo using ROS.
Gazebo is a free and open source robot simulator in which we can test our own algorithms, design robots, and test robots in different simulated environments. Gazebo can accurately and efficiently simulate complex robots in indoor and outdoor environments. Gazebo is built with a physics engine with which we can create high-quality graphics and rendering.
The features of Gazebo are as follows:
- Dynamic simulation: Gazebo can simulate the dynamics of a robot using physics engines such as Open Dynamics Engine (ODE). (http://opende.sourceforge.net/), Bullet (http://bulletphysics.org/wordpress/), Simbody (https://simtk.org/home/simbody/), and DART (http://dartsim.github.io/).
- Advanced 3D graphics: Gazebo provides high-quality rendering, lighting, shadows, and texturing using the OGRE framework (http://www.ogre3d.org/).
- Sensor support: Gazebo supports a wide range of sensors, including laser range finders, Kinect-style sensors, 2D/3D cameras, and so on. We can also use it to simulate noise to test audio sensors.
- Plugins: We can develop custom plugins for the robot, sensors, and environmental controls. Plugins can access Gazebo's API.
- Robot models: Gazebo provides models for popular robots, such as PR2, Pioneer 2 DX, iRobot Create, and TurtleBot. We can also build custom models of robots.
- TCP/IP transport: We can run simulations on a remote machine and a Gazebo interface through a socket-based message-passing service.
- Cloud simulation: We can run simulations on the cloud server using the CloudSim framework (http://cloudsim.io/).
- Command-line tools: Extensive command-line tools are used to check and log simulations.
Gazebo can be installed as a standalone application or an integrated application along with ROS. In this chapter, we will use Gazebo along with ROS to simulation a robot's behavior and to test our written code using the ROS framework.
If you want to try the latest Gazebo simulator yourself, you can follow the steps given at http://gazebosim.org/download.
To work with Gazebo and ROS, we don't need to install them separately because Gazebo comes with the ROS desktop full installation.
The ROS package that integrates Gazebo with ROS is called gazebo_ros_pkgs. There are wrappers around the standalone Gazebo. This package provides the necessary interface to simulate a robot in Gazebo using ROS message services.
The complete gazebo_ros_pkgs can be installed in ROS Indigo using the following command:
$ sudo apt-get install ros-kinetic-gazebo-ros-pkgs ros-kinetic-
Assuming that the ROS environment is properly set up, we can start roscore before starting Gazebo using the following command:
The following command will run Gazebo using ROS:
$ rosrun gazebo_ros gazebo
Gazebo runs two executables-the Gazebo server and the Gazebo client. The Gazebo server will execute the simulation process and the Gazebo client can be the Gazebo GUI. Using the previous command, the Gazebo client and server will run in parallel.
The Gazebo GUI is shown in the following screenshot:
After starting Gazebo, the following topics will be generated:
$ rostopic list /gazebo/link_states /gazebo/model_states /gazebo/parameter_descriptions /gazebo/parameter_updates /gazebo/set_link_state /gazebo/set_model_state
We can run the server and client separately using the following commands:
- Run the Gazebo server using the following command:
$ rosrun gazebo_ros gzserver
- Run the Gazebo client using the following command:
$ rosrun gazebo_ros gzclient
This chapter was an introduction to Robot Operating System. The main goal of this chapter was to give you an overview of ROS, its features, how to install it, the basic concepts of ROS, and how to program it using Python. Along with this, we have looked at a robotics simulator called Gazebo, which can work with ROS. We have seen how to install and run Gazebo. In the next chapter, we will look at the basic concepts of differential drive robots.
- What are the important features of ROS?
- What are the different levels of concepts in ROS?
- What is ROS catkin build system?
- What are ROS topics and messages?
- What are the different concepts of the ROS Computation Graph?
- What is the main function of the ROS Master?
- What are the important features of Gazebo?