Robot Programming | Robot Operating System (ROS)

Robot Programming

Robot Programming Using Robot Operating System (ROS) 2019

This blog explains Robot Operating System and robot programming. After this, we learn more about ROS, how to install ROS and its architecture. 

 

After this, we look at ROS concepts, ROS command tools, and ROS examples to demonstrate ROS capabilities. After that, we discuss the basics of ROS GUI tools and the Gazebo simulator. In the end, we learn how to set up a TurtleBot 3 simulator in ROS.

 

What Is Robot Programming?

Robot Programming

As you know, a robot is a machine with sensors, actuators (motors), and a computing unit that behaves based on user controls, or it can make its own decisions based on sensors inputs.

 

We can say the brain of the robot is a computing unit. It can be a microcontroller or a PC. The decision making and actions of the robot completely depend on the program running the robot’s brain.

 

This program can be firmware running on a microcontroller, or C/C++ or Python code running on a PC or a single board computer, like the Raspberry Pi. Robot programming is the process of making the robot work from writing a program for the robot’s brain (i.e., the processing unit).

 

The main components of any robot are the actuators and the sensors. Actuators move a robot’s joints, providing rotary or linear motion. Servo, Stepper, and DC gearmotors are actuator brands. Sensors provide the robot’s state and environment. Examples of robot sensors include wheel encoders, ultrasonic sensors, and cameras.

 

Actuators are controlled by motor controllers and interface with a microcontroller/PLC (programmable logic controller). Some actuators are directly controlled through a PC’s USB. Sensors also interface with a microcontroller or PC.

 

Ultrasonic sensors and infrared sensor interface with a microcontroller. High-end sensors like cameras and laser scanners can interface directly with the PC. There is a power supply/battery to power all the robotic components.

 

There is an emergency stop push-­ button to stop/reset the robot’s operation. The two major parts in which to program inside a robot is a PC and a microcontroller/PLC. PLCs are mainly using in industrial robots.

 

In short, we can say robot programming is programming the PC/SBC and microcontroller/PCL inside robot for performing a specific application using actuators and feedback from various sensors. The robot applications include pick and place of the object, moving the robot from A to B.

 

A variety of programming languages can program robots. C/C++, Python, Java, C #, and so forth are used with PCs. Microcontrollers use Embedded C, the Wiring language (based on C++), which is used in Arduino, and Mbed programming (https://os.mbed.com).

 

Industrial robot applications use SCADA or vendors’ proprietary programming languages, such as ABB and KUKA. This programming is done from the industrial robot’s teach pendant. RAPID is the programming language used in ABB industrial robots to automate robotic applications.

 

Robotic programming creates intelligence in the robot for self-decision making, implementing controllers like PID to move joints, automating repeated tasks, and creating robotic vision applications.

 

Why Robot Programming Is Different

Robot Operating System (ROS)

Robot programming is a subset of computer programming. Most robots have a “brain” that can make decisions. It can be a microcontroller or a PC. The differences between robot programming and conventional programming are the input and output devices.

 

The input devices include robot sensors, teach pendants, and touch screens and the output devices include LCD displays and actuators.

 

Any of the programming languages can program robots, but good community support, performance, and prototyping time make C++ and Python the most commonly used.

The following are some of the features needed for programming a robot.

 

Threading:

As seen in the robot block diagram, there are a number of sensors and actuators in a robot. We may need a multithreaded compatible programming language in order to work with different sensors and actuators in different threads. This is called multitasking. Each thread can communicate with each other to exchange data.

 

High-level object-oriented programming:

As you already know, object-oriented programming languages are more modular and code can easily reuse. The code maintenance is also easy compared to non-object-­ oriented programming languages. These qualities create better software for robots.

 

Low-level device control:

The high-level programming languages can also access low-level devices such as GPIO (general purpose input/output) pins, Serial ports, parallel ports, USB, SPI, and I2C. Programming languages like C/C++ and Python can work with low-level devices, which is why these languages prefer single-board computers like the Raspberry Pi and Android.

 

Ease of prototyping:

The easiness in prototyping a robot algorithm is definitely a choice in the selection of programming language. Python is a good choice in prototyping robot algorithms quickly.

 

Interprocess communication:

A robot has lot of sensors and actuators. We can use multithreading architecture or write an independent program for doing each task; for example, one program takes images from a camera and detects a face, another program sends data to an embedded board. These two programs can communicate with each other to exchange data.

 

This feature creates multiple programs instead of a multithreading system. The multithreading system is more complicated than running multiple programs in parallel. Socket programming is an example of interprocess communication.

 

Performance:

If we work with high-bandwidth sensors, such as depth cameras and laser scanners, the computing resources needed to process the data is obviously high. A good programming language can only allocate appropriate computing resource without loading the computing resource. The C++ language is a good choice to handle this kind of scenario.

 

Community support:

When choosing any programming language for robot programming, make sure that there is enough community support for that language, including forums and blogs.

 

Availability of third-party libraries:

The availability of third-party libraries can make our development easy; for example, if we want to do image processing, we can use libraries like OpenCV. If your programming language has OpenCV support, it is easier to do image processing applications.

 

Existing robotics software framework support:

There are existing robotics software frameworks such as ROS to program robots. If your programming language has ROS support, it is easier to prototype a robot application.

 

Getting Started with ROS

ROS

So far, we have discussed robot programming and how it is different from another computer programming. In this section, we look at a unique software platform for programming robots: the Robot Operating System, or ROS (www.ros.org).

 

ROS is a free and open source robotics software framework that is used in both commercial and research applications. The ROS framework provides the following robot-programming capabilities.

 

Message passing interface between processes.

ROS provides a message passing interface to communicate between two programs or processes. For example, a camera processes an image and finds coordinates in the image, and then these coordinates are sent to a tracker process.

 

The tracker process does the tracking of the image by using motors. As mentioned, this is one of the features needed to program a robot. It is called interprocess communication because two processes are communicating with each other.

 

Operating system–like features.

As the name says, ROS is not a real operating system. It is a meta-operating system that provides some operating system functionalities. These functionalities include multithreading, low-level device control, package management, and hardware abstraction.

 

The hardware abstraction layer enables programmers to program a device. The advantage is that we can write code for a sensor that works the same way with different vendors. So, we don’t need to rewrite the code when we use a new sensor.

 

Package management helps users organize software in units called packages. Each package has the source code, configuration files, or data files for a specific task. These packages can be distributed and installed on other computers.

 

High-level programming language support and tools.

The advantage of ROS is that it supports popular programming languages used in robot programming, including C++, Python, and Lisp. There is experimental support for languages such as C #, Java, Node.js, and so forth. The complete list is at http://wiki.ros.org/ Client%20Libraries.

 

ROS provides client libraries for these languages, meaning the programmer can get ROS functionalities in the languages mentioned. For example, if a user wants to implement an Android application that is using ROS functionality, the rosjava client library can be used. ROS also provides tools to build robotics applications.

 

With these tools, we can build many packages with a single command. This flexibility helps programmers spend less time in creating build systems for their applications.

 

Availability of third-party libraries.

The ROS framework is integrated with the most popular third-party libraries; for example, OpenCV (https://opencv.org) is integrated for robotic vision, and PCL (http://pointclouds.org) is integrated for 3D robot perception. These libraries make ROS stronger, and the programmer can build powerful applications on top of it.

 

Off-the-shelf algorithms.

This is a useful feature. ROS has implemented popular robotics algorithms such as PID (http://wiki.ros.org/pid); SLAM (Simultaneous Localization and Mapping) (http://wiki.ros.org/ gmapping); and path planners such as A*, Dijkstra (http://wiki.ros.org/global_planner), and AMCL (Adaptive Monte Carlo Localization) (http://wiki. ros.org/amcl).

 

The list of algorithm implementations in ROS continuous. The off-the-shelf algorithms reduce development time for prototyping a robot.

 

Ease in prototyping.

One advantage of ROS is off-the-­ shelf algorithms. Along with that, ROS has packages that can be easily reused with any robot; for example, we can easily prototype our own mobile robot by customizing an existing mobile robot package available in the ROS repository.

 

We can easily reuse the ROS repository because most of the packages are open source and reusable for commercial and research purposes. So, this can reduce robot software development time.

 

Ecosystem/community support

The main reason for the popularity and development of ROS is community support. ROS developers are all over the world. They actively develop and maintain ROS packages.

 

The big community support includes developers asking questions related to ROS. ROS Answers is a platform for ROS-related queries (https://answers.ros.org/ questions/). ROS Discourse is an online forum in which ROS users discuss various topics and publish news related to ROS (https://discourse.ros.org).

 

Extensive tools and simulators.

ROS is built with many command-line and GUI tools to debug, visualize, and simulate robotics applications. These tools are very useful for working with a robot. For example, the Rviz (http://wiki.ros.org/rviz) tool is used for visualization with cameras, laser scanners, inertial measurement units, and so forth. For working with robot simulations, there are simulators such as Gazebo (http://gazebosim.org).

 

The History of ROS

ROS

The following are some ROS project historic milestones.

The ROS project started at Stanford University in 2007, led by roboticist Morgan Quigly (http://people. osrfoundation.org/morgan/). In the beginning, it was a group of software developed for robots at Stanford.

 

Later in 2007, a robotics research startup called Willow Garage (http://www.willowgarage.com/) took over the project and coined the name ROS, which stands for Robot Operating System.

  • In 2009, ROS 0.4 was released, and a working ROS robot called PR2 was developed.
  • In 2010, ROS 1.0 was released. Many of its features are still in use.
  • In 2010, ROS C Turtle was released.
  • In 2011, ROS Diamondback was released.
  • In 2011, ROS Electric Emys was released.
  • In 2012, ROS Fuerte was released.
  • In 2012, ROS Groovy Galapagos was released.
  • In 2012, the Open Source Robotics Foundation (OSRF) takes over the ROS project.
  • In 2013, ROS Hydro Medusa was released.
  • In 2014, ROS Indigo Igloo was released, this was the first long-term support (LTS) release, meaning updates and support is provided for a long period of time (typically five years).
  • In 2015, ROS Jade Turtle was released.
  • In 2016, ROS Kinetic Kame was released. It is the second LTS version of ROS.
  • In 2017, ROS Lunar Loggerhead was released.
  • In May 2018, the twelfth version of ROS, Melodic Morenia, was released.

 

The timeline of the ROS project and more detailed history is available in at www.ros.org/history/. Each version of ROS is called a ROS distribution. You may be aware of the Linux distribution, such as Ubuntu, Debian, Fedora, and so forth.

 

If you are looking for the latest ROS features, you can choose new distributions, and if you are looking for stable packages, you can choose LTS. In Figure, the recommended distribution is ROS Kinetic Kame. In this post, the examples use Kinetic Kame.

ROS is now developed and maintained by the Open Robotics, previously known as the Open Source Robotics Foundation (www.osrfoundation.org).

 

Before and After ROS

Before and After ROS

 

There was active development in robotics before the ROS project, but there was no common platform and community for developing robotics applications. Each developer created software for their own robot, which in most cases, couldn’t be reused for any other robot. Developers had to rewrite code from scratch for each robot, which takes a lot of time.

 

Also, most of the code was not actively maintained, so there was no support for the software. Also, developers needed to implement standard algorithms on their own, which took more time to prototype the robot.

 

After the ROS project, things changed. Now there is a common platform for developing robotics applications. It is a free and open source for commercial and research purposes.

 

Off-the-shelf algorithms are readily available, so there is no longer a need to code. There is big community support, which makes development easier. In short, the ROS project changed the face of robotics programming.

 

Why Use ROS?

Why Use ROS?

This is a common question that developers ask when looking for a platform to program ROS. Although ROS has many features, there are still areas in which ROS can’t be used or is not recommended to use.

 

In the case of a self-driving car, for example, we can use ROS to make a prototype, but developers do not recommend ROS to make the actual product.

 

This is due to various issues, such as security, real-time processing, and so forth. ROS may not be a good fit in some areas, but in other areas, ROS is an absolute fit.

 

In corporate robotics research centers and at universities, ROS is an ideal choice for prototyping. And ROS is used in some robotics products after a lot of fine-tuning (but not self-driving cars).

 

A project called ROS 2.0 is developing a much better version of the existing ROS in terms of security and real-time processing (https:// github.com/ros2/ros2/wiki). ROS 2.0 may become a good choice for robotics products in the future.

 

Installing ROS

Installing ROS

This is an important step in ROS development. Installing ROS on your PC is a straightforward process. Before installing, you should be aware of the various platforms that support ROS. The figure shows various operating systems on which you can install ROS. As discussed, ROS is not an operating system, but it needs a host. 

 

Ubuntu Linux is the most preferred OS for installing ROS. ROS supports Ubuntu 32-bit, 64-bit, ARM 32-bit, and ARM 64-bit. This means ROS can run on PC/desktops and on single-board computers like Raspberry Pi (http://raspberrypi.org), Android, and NVIDIA TX1/TX2. Debian Linux has good ROS support.

 

In OS X and other operating systems, ROS is still in the experimental phase, which means that ROS functionalities are not yet available.

Let’s move on to installation. If you are using a PC or an ARM board running Ubuntu armhf or arm64, you can follow the procedures at http:// wiki.ros.org/ROS/Installation. 

 

When you go to this wiki, it asks which ROS version you need to install. As mentioned, we are choosing ROS Kinetic Kame because it is LTS and stable. If you want to try the latest ROS features, use Lunar Loggerhead. After you click the distribution that you want, you get the list of operating systems that support that distribution. 

 

Choose the Ubuntu 16.04 (Xenial) operating system. When you select the operating system, you get a set of instructions. The wiki at http:// wiki.ros.org/kinetic/Installation/Ubuntu provides direct access to instructions for setting ROS in Ubuntu.

 

We can install ROS in two ways: through a binary installation or by source compilation. The first method is easy and less time-consuming. Binary installation lets you directly install ROS from prebuilt binaries. With source compilation, you create an executable by compiling ROS source code. This takes more time and is based on your PC’s specifications.

 

The following describes the installation steps.

  • \ 1)\ Configure the Ubuntu repositories. An Ubuntu repository is where the Ubuntu software is organized, typically on servers in which users can access and install the application. There following are repositories in Ubuntu.
  • \ a)\ Main: Ubuntu officially supported free and open source software
  • \ b)\ Universe: Community-maintained free and open source software
  • \ c)\ Restricted: This has proprietary device drivers
  • \ d)\ Multiverse: Software restricted by copyright and legal issues

 

To install ROS, we have to enable access to the entire repository so that Ubuntu can retrieve packages from these repositories. The figure shows how to do this. Just search in Ubuntu for “Software & Updates”.

 

You can also select the server location. You can either use a server from your country or the Ubuntu main server. OK, you are done with the first step.

 

\ 2)\ Set up your sources.list. This is an important step in ROS installation. It adds the ROS repository information where the binaries are stored. Ubuntu can fetch the packages after this step is completed. The following is the command used for this.

 

Note Execute the following commands in a terminal.

$ sudo sh -c 'echo "deb http://packages.ros. org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'

This command creates a new file called /etc/apt/ sources.list.d/ros-latest.list and adds the following line to it.

 

"deb http://packages.ros.org/ros/ubuntu xenial main".

If we create this file in the sources.list folder and add this line, then only Ubuntu package manager can fetch the package list.

Note If you execute $ lsb_release -sc in a terminal, you get the output 'xenial'.

 

\ 3)\ Add the keys.

In Ubuntu, if we want to download a binary or a package, we have to add a secure key in our system to authenticate the downloading process. The package that authenticates using these keys is trusted. The following is the command to add the keys.

$ sudo apt-key adv --keyserver hkp:// sks.mj2.uk (node 3):80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116

 

\ 4)\ Update the Ubuntu package list.

When we update the list, the packages from the ROS repositories also list. We use the following command to update the Ubuntu repository.

$ sudo apt-get update

 

\ 5)\ Install ROS Kinetic packages.

After getting the list, we download and install the package using the following command.

$ sudo apt-get install ros-kinetic-desktop-full

 

This command installs all the necessary packages in ROS, including tools, simulators, and essential robot algorithms. It takes time to download and install all these packages.

 

\ 6)\ Initialize rosdep.

After installing all packages, we need to install a tool called rosdep, which is useful for installing the dependent packages of a ROS package. For example, a typical ROS package may have a few dependent packages to work properly. rosdep checks whether the dependent packages are available and if not, it automatically installs them.

 

The following command installs the rosdep tool.

$ sudo rosdep init

$ rosdep update

 

\ 7)\ Set the ROS environment.

This is an important step after installing ROS. As discussed earlier, ROS comes with tools and libraries. To access these command-line tools and packages, we have to set up the ROS environment to access these commands, even though its installed on our system. The following command adds a line in the .bashrc file in your home folder, which sets the ROS environment in every new terminal.

 

$ echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc

bashrc file

Next, enter the following command to add the environment in the current terminal.

$ source ~/.bashrc

Yes, you are almost done. A small step remains.

\ 8)\ Set up dependencies for building the package.

 

The use of this step can be explained using an example. Imagine that you are working with a robot with more than 100 packages. If you want to set up those packages on a computer, it is difficult to manage all the dependencies needed to install those packages.

 

In that situation, tools like rosinstall are useful. This tool installs all the packages in a single command. In this step, we are literally installing those kinds of tools.

$ sudo apt-get install python-rosinstall python-rosinstall-generator python-wstool build-essential

Congratulations, you are done with installation. You can verify that your installation is correct by using the following command.

$ rosversion -d

If you are getting 'kinetic' as the output, you are all set with the installation.

[Note: You can free download the complete Office 365 and Office 2019 com setup Guide for here]

 

Robots and Sensors Supporting ROS

Robots and Sensors Supporting ROS

 

The figure shows some of the popular robots that use ROS. A complete list of robots working in ROS is at http://robots.ros.org.

\ a)\ Pepper (www.ald.softbankrobotics.com/en/ robots/pepper): A service robot used for assisting people in a variety of ways.

\ b)\ REEM-C (http://pal-robotics.com/en/products/ reem-c/): A full-­size humanoid robot that is mainly used for research purposes.

\ c)\ TurtleBot 2 (www.turtlebot.com/turtlebot2/): A simple mobile robot platform that is mainly used for research and educational purposes.

\ d)\ Robonaut 2 (https://robonaut.jsc.nasa.gov/ R2/): A NASA robot designed to automate various tasks on the International Space Station.

\ e)\ Universal Robot arm: (www.universal-robots.com/products/ur5-robot): One of the popular semi-industrial robots widely used for automating various tasks in manufacturing.

 

There are also sensors supported by ROS. A complete list of these sensors is available at http://wiki.ros.org/Sensors .

\ a)\ Velodyne (http://velodynelidar.com): Popular LIDARs mainly used in self-driving cars.
\ b)\ ZED Camera (www.stereolabs.com): A popular stereo depth camera.
\ c)\ TeraRanger (www.terabee.com): A new sensor for depth sensing in 2D and 3D.
\ d)\ Xsense MTi IMU (www.xsens.com/products/): An accurate IMU solution.
\ e)\ Hokuyo Laser (www.hokuyo-aut.jp/): A popular laser scanner.
\ f)\ Intel RealSense (https://realsense.intel.com: A 3D depth sensor for robot navigation and mapping.

 

Popular ROS Computing Platforms

ros

\ a)\ NVIDIA TX1/TX2 (www.nvidia.com/en-us/ autonomous-machines/embedded-systems-­ dev-kits-modules/): Capable of running deep learning applications and computational intensive applications. The board has an ARM-based 64-bit processor that can run Ubuntu. This platform is very popular in autonomous robotics applications, especially drones.

 

\ b)\ Raspberry Pi 3 (www.raspberrypi.org/products/ raspberry-pi-3-model-b/): Very popular single-board computers for education and research. Robotics is a key area.

 

\ c)\ Intel NUC (www.intel.com/content/www/us/en/ products/boards-kits/nuc.html): Based on an x86_64 platform, which is basically a miniature version of a desktop computer.

 

\ d)\ Odroid XU4 (www.hardkernel.com/main/main.php): The Odroid series boards are similar to Raspberry Pi, but it has better configuration and performance. It is based on the ARM architecture.

 

ROS Architecture and Concepts

ROS Architecture and Concepts

We have discussed ROS, its features, and how to install it. In this section, we go deep into ROS architecture and its important concepts. Basically, ROS is a framework to communicate between two programs or process.

 

For example, if program A wants to send data to program B, and B wants to send data to program A, we can easily implement it using ROS. So the question is whether we implement it using socket programming directly. Yes, we can, but if we build more and more programs, it gets complex, so ROS is a good choice for interprocess communication.

 

 Do we really need interprocess communication in a robot? Can we program a robot without it? 

 

A robot may have many sensors and actuators, as well as a computing unit. How we can control many actuators and process so much sensor data? Can we do it in a single program? Yes, but that is not a good way of doing it.

 

The better way is, we can write independent programs to handle sensor data and controlling actuators, and often we may need to exchange data between these programs. This is the situation where we use ROS.

 

So can we program a robot without ROS? Yes, but the complexity of software increases according to the number of actuators and sensors. Let’s see how the communication is happening between two programs in ROS.

 

The figure shows two programs marked as node 1 and node 2. When any of the programs start, a node communicates to a ROS program called the ROS master.

 

The node sends all its information to the ROS master, including the type of data it sends or receives. The nodes that are sending data are called publisher nodes, and the nodes that are receiving data are called subscriber nodes.

 

The ROS Master has all the publisher and subscriber information running on computers. If node 1 sends particular data called “A” and the same data is required by node 2, then the ROS master sends the information to the nodes so that they can communicate with each other.

 

The ROS nodes can send different types of data to each other, which includes primitive data types such as integer, float, string, and so forth. The different data types being sent are called ROS messages.

 

With ROS messages, we can send data with a single data type or multiple data with different data types. These messages are sent through a message bus or path called ROS topics. Each topic has a name; for example, a topic named “chatter” sends a strong string message.

 

When a ROS node publishes a topic, it sends a ROS topic with a ROS message, and it has data with the message type. In Figure, the ROS topic is publishing and subscribing node 1 and node 2. This process starts when the ROS master exchanges the node details to each other.

 

Next, let’s go through some important concepts and terms that are used when working with ROS. They can be classified into three categories: the ROS file system, ROS computation concepts, and the ROS community.

 

The ROS File System

ROS File System

The ROS file system includes packages, meta-packages, package manifests, repositories, message types, and services types. ROS packages are the individual units, or the atomic units, of ROS software.

 

All source code, data files, build files, dependencies, and other files are organized in packages. ROS meta package groups a set of similar packages for a specific application. AROS meta package does not have any source files or data files. It has the dependencies of similar packages. A ROS meta package organizes a set of packages.

 

package manifest is an XML file placed inside a ROS package. It has all the primary information of a ROS package, including the name of the package, description, author, dependencies, and so forth. A typical package.xml is shown next.

<?xml version="1.0"?>
<package>
<name>test_pkg</name>
<version>0.0.1</version>
<description>The test package</description>
<maintainer email="qboticslabs@gmail.com">robot</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
................. ............... .
<run_depend>catkin</run_depend>
....... . ............ .
</package>

 

ROS repository is a collection of ROS packages that share a common version control system.

 

message type description is the definition of a new ROS message type. There are existing data types available in ROS that can be directly used for our application, but if we want to create a new ROS message, we can. 

 

A new message type can be defined and stored inside the msg folder inside the package. Similar to the message type, a service type definition contains our own service definitions. It is stored in the srv folder.

 

ROS Computation Concepts

These are the terms associated with ROS computation concepts.

ROS nodesProcess that use ROS APIs to perform computations.

ROS master: An intermediate program that connects ROS nodes.

 

ROS parameter server: A program that normally runs along with the ROS master. The user can store various parameters or values on this server and all the nodes can access it. The user can set the privacy of the parameter too. If it is a public parameter, all the nodes have access; if it is private, only a specific node can access the parameter.

 

ROS topics: Named buses in which ROS nodes can send a message. A node can publish or subscribe to any number of topics.

 

ROS messageThe messages are basically going through the topic. There are existing messages based on primitive data types, and users can write their own messages.

 

ROS service: We have already seen ROS Topics, which is having publishing and subscribing mechanism. The ROS Service has a Request/Reply mechanism. A service call is a function, which can call whenever a client node sends a request. The node who create a service call is called Server node and who call the service is called client node.

 

ROS bags: A useful method to save and playback ROS topics. Also useful for logging the data from a robot to process it later.

 

The ROS Community

 The ROS Community

The following are terms used to exchange ROS software and knowledge.

  • The ROS distribution is a collection of versioned packages.
  • The ROS wiki has tutorials on how to set up and program ROS.
  • ROS Answers (https://answers.ros.org/questions/) has ROS queries and solutions, similar to Stack Overflow.
  • ROS discourse (https://discourse.ros.org) is a forum in which developers can share news and ask queries related to ROS. If you want to learn more about ROS concepts, visit http://wiki.ros.org/ROS/Concepts.

 

ROS Command Tools

ROS Command Tools

This section discusses ROS command-line tools. What are these tools for? The tools can make our lives easier. There are different ROS tools that we can use to explore various aspects of ROS.

 

We can implement almost all the capabilities of ROS using these tools. The command-line tools are executed in the Linux terminal; like the other commands in Linux, we get the ROS command tools too.

 

The roscore command is a very important tool in ROS. When we run this command in the terminal, it starts the ROS master, the parameter server, and a logging node. We can run any other ROS program/node after running this command.

 

So run roscore on one terminal window, and use another terminal window to enter the next command to run a ROS node. If you run roscore in a terminal, you may get messages like the ones shown in Figure 

 

You can see messages in the terminal about starting the ROS master. You also see the ROS master address. The rosnode command explores all the aspects of a ROS node. For example, we can list the number of ROS nodes running on our system.

If you type any of the commands, you get complete help for the tool. The following is a common usage of rosnode.

$ rosnode list

 

The rostopic command provides information about the topics publishing/subscribing in the system. This command is very useful for listing topics, printing topic data, and publishing data.

$ rostopic list

 

If there is a topic called /chatter, we can print/echo the topic data using the following command.

$ rostopic echo /chatter

 

If we want to publish a topic with data, we can easily do this command.

$ rostopic pub topic_name msg_type data

The following is an example.

$ rostopic pub /hello std_msgs/String "Hello"

You can echo the same topic after publishing too. Note that if you run these commands in one terminal, roscore should be running.

 

The figure is the Terminator (https://launchpad.net/terminator) application in which the screen is split into separate terminal sessions. One session is running roscore. A second session is publishing a topic. A third session is echoing the same topic. The ios version command checks your ROS version.

 

The following command retrieves the current ROS version.

$ rosversion -d

Output: kinetic

The rosparam command gives a list of parameters loaded in the parameter server.

You can use the following command to list the parameters in the system.

$ rosparam list

You can get the command here.
Setting parameter
$ rosparam set parameter_name value Eg. $ rosparam set hello "Hello"
Getting a parameter
$ rosparam get parameter_name
$ rosparam get hello
Output: "Hello"

 

The roslaunch command is also useful in ROS. If you want to run more than ten ROS nodes at time, it is very difficult to launch them one by one. In this situation, we can use roslaunch files to avoid this difficulty.

 

ROS launch files are XML files in which you can insert each node that you want to run. Another advantage of the roslaunch command is that the roscore command executes with it, so we don’t need to run an additional roscore command for running the nodes.

 

The following is the syntax for running a roslaunch file. The 'roslaunch' is the command to run a launch file, along with that we have to mention package name and name of launch file.

$ roslaunch ros_pkg_name launch_file_name

roslaunch roscpp_tutorials talker_listener.launch is an example.

 

To run a ROS node, you have to use the rosrun node. Its usage is very simple.

$ rosrun ros_pkg_name node_name

rosrun roscpp_tutorials talker is an example.

ROS Demo: Hello World Example

 

This section demonstrates a basic ROS example. The example is already installed in ROS.

There are two nodes: talker and listener. The talker node publishes a string message. The listener node subscribes to it. In this example of the process, the talker publishes a Hello World message and the listener subscribes to it and prints it.

 

The figure shows a diagram of the two nodes. As discussed earlier, both nodes need to communicate with the ROS master to get the information from the other node.

 

Communication between talker and listener nodes

Let’s start the example by using the following command.

The first step in starting any node in ROS is roscore.

$ roscore

Start the talker node by using the following command in another terminal.

$ rosrun roscpp_tutorials talker

Now you see the messages printing on the terminal screen. If you list the topic by using the following command, you see a new topic called ­/chatter.

$ rostopic list

Output: /chatter

 

Now start the listener node by using the following command.

$ rosrun roscpp_tutorials listener

The subscribing begins between the two nodes

If you want to run two of the nodes together, use the roslaunch command.

$ roslaunch roscpp_tutorials talker_listener.launch

roscpp_tutorials is an existing package in ROS and talker_ listener.launch.

 

ROS Demo: turtlesim

This section demonstrates an interesting application for learning ROS concepts. The application is called turtlesim, which is a 2D simulator with a turtle in it.

You can move the turtle, read the turtle’s current position, and change the turtle’s pattern, and so forth using ROS topics, ROS services, and parameters. When working with turtlesim, you get a better idea of how to control a robot using ROS.

 

The turtlesim application is already installed on ROS. You can start this application by using the following commands.

Starting roscore

$ roscore

Starting Turtlesim application

$ rosrun turtlesim turtlesim_node

Now you can open a new terminal and list the topics by publishing the turtlesim node.

$ rostopic list

Moving the Turtle

Figure lists the services created by the turtlesim no

de. You can list the services by using the following command.

$ rosservice list
$ rosparam list

 

Moving the Turtle

If you want to move the turtle, start another ROS node by using the following command. This command has to start in another terminal.

$ rosrun turtleturtle_teleop_key

 

You can control the robot using your keyboard’s arrow keys. When you press an arrow key, it publishes velocity to /turtle1/cmd_vel, which makes the turtle move. If you want to see the back end of these nodes. It shows the topic data going to turtles.

 

Moving the Turtle in a Square

This section shows how to move the turtle along a straight path. Close all the running nodes by pressing Ctrl+C, and start a new turtle session using the following command.

Starting roscore

$ roscore

Moving the Turtle in a Square

Starting turtlenode

$ rosrun turtleturtlesim_node

Starting the node for drawing square $ rosrun turtledraw_square

The draw square in turtles

If we want to clear the turtles, we can call a service called /reset. $ rosservice call /reset This resets the turtle’s position

 

ROS GUI Tools Rviz and Rqt

Along with command-line tools, ROS has GUI tools to visualize sensor data. A popular GUI tool is Rviz. Using Rviz, we can visualize image data, 3D point clouds, and robot models, as well as transform data and so forth. This section explores the basics of the Rviz tool, which comes with the ROS installation.

 

Start Rviz using following the command.

Start roscore
$ roscore
Start rviz
$ rosrun rviz rviz

 

The following describes sections in Rviz.

3D viewportThe area to visualize the 3D data from sensors, robot transform data, 3D model data, and other kinds of 3D information.

Display panel: Displays various kinds of sensor data.

View panelOptions to view the 3D viewport according to the application.

ToolbarOptions for interacting with the 3D viewport, measuring robot position, setting the robot navigation goal, and changing the camera view.

 

Time panel: Features information about the ROS time and elapsed time. This time stamping may be useful for processing the sensor data.

Rqt: Features options to visualize 2D data, logging topics, publishing topics, calling services, and more. This is how to start the Rqt GUI.

 

Start roscore

$ roscore

Start rqt_gui

$ rosrun rqt_gui rqt_gui

You get an empty GUI with some menus. You can add your own plug-ins from the drop-down menu. Figure is a screenshot of rqt_gui loaded with a plug-in.

 

Programming with ROS

 Programming with ROS

The post covers creating a ROS workspace, ROS package, and ROS nodes. After creating the package and basic ROS nodes, you will see how to program the turtle simulator from the previous post.

 

Next, you are introduced to the Gazebo simulator and TurtleBot robot simulation, creating basic ROS nodes to move the TurtleBot in the simulation. Afterward, you learn how to interface and program an Arduino and Tiva-C Launchpad using ROS. These tutorials are very useful for when we create our own robot.

 

At the end of the post, you see how to set up ROS and program it in the Raspberry Pi 3. To implement a new ROS topic, or a new ROS message, or a ROS service, we can simply call these ROS built-in functions to create it.

 

We don’t need to implement ROS features from scratch. The programs that use ROS built-­ in functions/APIs (application program interface) are called ROS nodes.

 

In this post, we create ROS nodes for different applications. The ROS wiki provides extensive documentation on creating ROS nodes. As a beginner, it may be difficult to understand most of the topics mentioned on the ROS wiki. This post gives you a brief look at them to get started with ROS programming.

 

There are some steps that we need to take before proceeding to ROS programming. The first step is to create a ROS workspace. The next section discusses the ROS workspace and how to create it.

 

Creating a ROS Workspace and Package

Creating a ROS Workspace and Package

The first step in ROS development is the creation of the ROS workspace, which is where ROS packages are kept. We can create new packages, install existing packages, build and create new executables.

 

You must first create a ROS workspace folder. You can give it any name, and you can create it in any location. Normally, this is in the Ubuntu home folder.

 

At a new terminal, enter the following command. This creates a folder called catkin_ws, inside of which is another folder called class='lazy' data-src. The ROS workspace is also called the catkin workspace. You see more of catkin in the next section.

$ mkdir -p ~/catkin_ws/class='lazy' data-src

 

The name of the class='lazy' data-src folder shouldn’t be changed. You can change the workspace folder name, however.

After entering the command, switch to the class='lazy' data-src folder by using the cd command.

$ cd catkin_ws/class='lazy' data-src

The following command initializes a new ROS workspace. If you are not initializing a workspace, you cannot create and build the packages properly.

$ catkin_init_workspace

After this command, you should see the message in Figure on your terminal.

There is a CMakeLists.txt inside the class='lazy' data-src folder.

After initializing the catkin workspace, you can build the workspace. You can able it to build the workspace without any packages. To build the workspace, switch from the catkin_ws/class='lazy' data-src folder to the catkin_ws folder.

$ ~/catkin_ws/class='lazy' data-src$ cd ..

 

workspace

The command to build the catkin workspace is catkin_make.

$ ~/catkin_ws$ catkin_make

You get the following output after entering this command.

 

Now you can see a few folders in addition to the class='lazy' data-src folder. More information about the building process is in the next section. The class='lazy' data-src folder is where our packages are kept. If you want to create or build a package, you have to copy those packages to the class='lazy' data-src folder. After creating the workspace, it is an important thing to add the workspace environment.

 

This means you have to set the workspace path so that the packages inside the workspace become accessible and visible. To do this, you have to do the following steps.

 

Open the .bashrc file in the home folder and add the following line at the end of the file.

At a terminal, switch to the home folder and select the .bashrc file.

$ gedit .bashrc

Add the following line at the end of .bashrc.

source ~/catkin_ws/devel/setup.bash

 

As you already know, the .bashrc script in the home folder executes when a new terminal session starts. So, the command inserted in the .bashrc file also executes.

setup.bash in the following command has variables to add to the Linux environment.

source ~/catkin_ws/devel/setup.bash

catkin_make output

When we source this file, the workspace path is added in the current terminal session. Now when we use any terminal, we can access the packages inside this workspace.

 

Before discussing the creation of packages, we need to discuss the catkin build system in ROS. You get a better idea of the building process when you are aware of the catkin build system.

 

ROS Build System

ROS Build System

The target can be an executable or a library. In ROS, there is a build system for compiling ROS packages. The name of the build system that we are using is catkin (http://wiki.ros.org/catkin). catkin is a custom build system made from the CMake build system and Python scripting.

 

So why not directly use CMake? The answer is simple: building a set of ROS packages is complicated. The complexity increases with the number of packages and packages dependencies. The catkin build system takes cares of all these things. You can read more about the catkin build system at http://wiki.ros.org/catkin/conceptual_overview.

 

ROS Catkin Workspace

We have created a catkin workspace but didn’t discuss how it works. The workspace has several folders. Let’s look at the function of each folder.

 

class='lazy' data-src Folder

The class='lazy' data-src folder inside the catkin workspace folder is the place where you can create, or clone, new packages from repositories. ROS packages only build and create an executable when it is in the class='lazy' data-src folder. When we execute the catkin_make command from the workspace folder, it checks inside the class='lazy' data-src folder and builds each package.

 

build Folder

When we run the catkin_make command from the ROS workspace, the catkin tool creates some build files and intermediate cache CMake files inside the build folder. These cache files help prevent from rebuilding all the packages when running the catkin_make command;

 

for example, if you build five packages, and then add a new package to the class='lazy' data-src folder, only the new package builds during the next catkin_make command. This is because of those cache files inside the build folder. If you delete the build folder, all the packages build again.

 

devel Folder

When we run the catkin_make command, each package is built, and if the build process is successful, the target executable is created. The executable is stored inside the devel folder, which has shell script files to add the current workspace to the ROS workspace path. We can access the current workspace packages only if we run this script. Generally, the following command is used to do this.

source ~/<workspace_name>/devel/setup.bash

 

We are adding this command in the .bashrc file so that we can access the workspace packages in all terminal sessions. If you go through the procedures to set up the catkin workspace, you see these steps.

 

install Folder

After building the target executable locally, run the following command to install the executable.

$ catkin_make install

 

It has to execute from the ROS workspace folder. If you do this, you see the install folder in the workspace. This folder keeps the install target files. When we run the executable, it executes from the install folder. There is more information about the catkin workspace at http:// wiki.ros.org/catkin/workspaces#Catkin_Workspaces.

 

Creating a ROS Package

We are done creating the ROS workspace. Next, let’s look at how to create a ROS package. The ROS package is where ROS nodes are organized— libraries and so forth. We can create a catkin ROS package by using the following command.

Synatx: $ catkin_create_pkg ros_package_name package_dependencies

 

The command that we use to create the package is catkin_create_ pkg. The first parameter for this command is the package name, and the dependencies of the package follow it; for example, we are going to create a package called hello_world with dependencies. We discuss more the dependencies in the next section.

 

You have to execute the command from the class='lazy' data-src folder in the catkin workspace.

$ /catkin_ws/class='lazy' data-src$ catkin_create_pkg hello_world roscpp rospy std_msgs

 

catkin_make

The structure of a ROS package is shown in Figure.

Inside the package are the class='lazy' data-src folder, package.xml, CMakeLists.txt, and the include folder.

CMakeLists.txt: This file has all the commands to build the ROS source code inside the package and create the executable.

package.xml: This is basically an XML file. It mainly contains the package dependencies, information, and so forth.

 

class='lazy' data-src: The source code of ROS packages are kept in this folder. Normally, C++ files are kept in the class='lazy' data-src folder. If you want to keep Python scripts, you can create another folder called scripts inside the package folder.

 

include: This folder contains the package header files. It can be automatically generated, or third-party library files go in it. The next section discusses ROS client libraries, which are used to create ROS nodes.

 

Using ROS Client Libraries

We have covered various ROS concepts like topics, services, messages, and so forth. How do we implement these concepts? The answer is by using ROS client libraries.

 

The ROS client libraries are a collection of code with functions to implement ROS concepts. We can simply include these library functions in our code to make it a ROS node. The client library saves development time because it provides the built-in functions to make a ROS application.

 

We can write ROS nodes in any programming language. If there is any ROS client for that programming language, it is easier to create ROS nodes; otherwise, we may need to implement our own ROS concepts.

 

The following are the main ROS client libraries.

roscpp: This is the ROS client library for C++. It is widely used for developing ROS applications because of its high performance.

 

rospy: This is the ROS client library for Python (http:// wiki.ros.org/rospy). Its advantage is saving development time. We can create a ROS node in less time than with roscpp.

 

It is ideal for quick prototyping applications, but performance is weaker than with roscpp. Most of the command line tools in ROS are coded using rospy such as roslaunch, roscore and so forth.

 

roslisp: This is the ROS client library of the Lisp language. It is mainly used in motion planning libraries on ROS, but it is not as popular as roscpp and rospy.

There are also experimental client libraries, including rosjava, rosnodejs, and roslua. The complete list of ROS client libraries is at http://wiki.ros.org/Client%20Libraries.

We will mainly work with roscpp and rospy. The next section shows a basic example of ROS nodes created using roscpp and rospy.

 

roscpp and raspy

This section discusses the various aspects of writing a node using client libraries such as roscpp and rospy. This includes the header files and modules used in ROS nodes, initializing a ROS node, publishing and subscribing a topic, and so forth.

 

Header Files and ROS Modules

When you write code in C++, the first section includes the header files. Similarly, when you write Python code, the first section imports Python modules. In this section, we look at the important headers files and modules that we need to import into a ROS node.

  • To create a ROS C++ node, we have to include the following header files. #include "ros/ros.h"
  • The ros.h has all the headers required to implement ROS functionalities.
  • We can’t create a ROS node without including this header file.

 

The next type of header file used in ROS nodes is a ROS message header. If we want to use a specific message type in our node, we have to include the message header file. ROS has some built-in message definition, and the user can also create a new message definition.

 

There is a built-in message package in ROS called std_msgs that has a message definition of standard data types, such as int, float, string, and so forth. For example, if we want to include a strong message in our code, we can use the following line of code.

 

#include "std_msgs/String.h"

Here, the first part is the package name and the next part is the message type name. If there is a custom message type, we can call it with the following syntax.

# include "msg_pkg_name/message_name.h"


The following are some of the messages in the std_msgs package.

#include "std_msgs/Int32.h"

#include "std_msgs/Int64.h"

 

The complete list of message types inside the std_msgs package is at http://wiki.ros.org/std_msgs.

 

In Python, we have to import modules to create a ROS node. The ROS module that we need to import is imported rospy, rospy has all the important ROS functions. To import a message type, we have to import the specific modules, like we did in C++.

The following is an example of importing a string message type in Python.

from std_msgs.msg import String

We have to use package_name.msg and import the required message type.

 

Initializing a ROS Node

Before starting any ROS node, the first function called initializes the node. This is a mandatory step in any ROS node.

In C++, we initialize using the following line of code.

int main(int argc, char **argv)

{

ros::init(argc, argv, "name_of_node")

.....................

}

 

After the int main() function, we have to include ros::init(), which initializes the ROS node. We can pass the argc,argv command-line arguments to the init() function and the name of the node. This is the ROS node name, and we can retrieve its list by using rosnode list.

In Python, we use the following line of code.

rospy.init_node('name_of_node', anonymous=True);

The first argument is the name of the node, and the second argument is anonymous=True, which means the node can run on multiple instances.

 

Printing Messages in a ROS Node

ROS provides APIs to log messages. These messages are a readable string that conveys the status of the node. In C++, the following functions log the node’s messages.

ROS_INFO(string_msg,args):Logging the information of node ROS_WARN(string_msg,args):Logging warning of the node ROS_DEBUG(string_msg,args):Logging debug messages ROS_ERROR(string_msg,args):Logging error messages ROS_FATAL(string_msg,args):Logging Fatal messages Eg:ROS_DEBUG("Hello %s","World");

 

In Python, there are different functions for the logging operations.

rospy.logdebug(msg, *args)

rospy.logerr(msg, *args)
rospy.logfatal(msg, *args)
rospy.loginfo(msg, *args)
rospy.logwarn(msg, *args)
Creating a Node Handle

 

After initializing the node, we have to create a NodeHandle instance that starts the ROS node and other operations, like publishing/subscribing a topic. We are using the ros:: NodeHandle instance to create those operations.

In C++, the following shows how to create an instance of ros:: NodeHandle.

ros::NodeHandle nh;

The rest of the operations in the node use the nh instance. In Python, we don’t need to create a handle; the rospy module internally handles it.

 

Creating a ROS Message Definition

Before publishing a topic, we have to create a ROS message definition. The message definition is created by using the following methods. In C++, we can create an instance of a ROS message with the following line of code; for example, this is how we create an instance of std_msgs/ String.

std_msgs::String msg;

After creating the instance of the ROS message, we can add the data by using the following line of code.

msg.data = "String data"

 

In Python, we use the following line of code to add data to the string message.

msg = String()

msg.data = "string data"

Publishing a Topic in ROS Node

 

This section shows how to publish a topic in a ROS node.

In C++, we use the following syntax.

ros::Publisher publisher_object = node_handle.advertise<ROS message type >("topic_name",1000)

After creating the publisher object, the publish() command sends the ROS message through the topic.

publisher_object.publish(message)

 

Example:

ros::Publisher chatter_pub = nh.advertise<std_ msgs::String>("chatter", 1000);

chatter_pub.publish(msg);

In this example, chatter_pub is the ROS publisher instance, and it is going to publish a topic with message type std_msgs/String and chatter as the topic name. The queue size is 1000.

 

In Python, the publishing syntax is as follows.

Syntax: publisher_instance = rospy.Publisher('topic_name', message_ type, queue_size)

Example:

pub = rospy.Publisher('chatter', String, queue_size=10)

pub.publish(hello_str)

This example publishes a topic called chatter with a std_msgs/String message type and a queue_size of 10.

 

Subscribing a Topic in ROS Node

When publishing a topic, we have to create a message type and need to send through the topic. When subscribing to a topic, the message is received from the topic.

 

In C++, the following is the syntax of subscribing to a topic.

ros::Subscriber subscriber_obj = node handle.subscribe ("topic_name", 1000, callback function)

When subscribing to a topic, we don’t need to mention the topic message type, but we do need to mention the topic name and a callback function. The callback function is a user-defined function that executes once a ROS message is received over the topic.

 

Inside the callback, we can manipulate the ROS message—print it or make a decision based on the message data. (Callback is discussed in the next section.)

 

The following is a subscription example of the "chatter" topic with the "chatterCallback" callback function.

ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

The following shows how to subscribe a topic in Python.

rospy.Subscriber("topic_name",message_type,callback funtion name")

 

The following shows how to subscribe to the "chatter" topic with the message type as a string, and a callback function. In Python, we have to mention the message type along with the Subscriber() function.

rospy.Subscriber("chatter", String, callback)

 

Writing the Callback Function in ROS Node

When we subscribe to a ROS topic and a message arrives in that topic, the callback function is triggered. You may have seen the mention of a callback function in the subscriber function. The following is the syntax and an example of the callback function in C++.

void callback_name(const ros_message_const_pointer &pointer)

{
//
Access data pointer->data
}
The following shows how to handle a ROS string message and print the data.
void chatterCallback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
The following shows how to write a callback in Python. It’s very similar to a Python function, which has an argument that holds the message data.
def callback(data):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)

 

The ROS Spin Function in ROS Node

After starting the subscription or publishing, we may have to call a function to process the request to subscribe and publish. In a C++ node, the ros::spinOnce() function should be called after publishing a topic, and the ros::spin() function should be called if you are only subscribing a topic. If you are doing both, use the spinOnce() function.

 

In Python, there is no spin() function, but you can use the rospy. sleep() function after publishing, or the rospy.spin() function if there is only subscription of the topic.

 

The ROS Sleep Function in ROS Node

If we want to make a constant rate inside a loop that is inside a node, we can use ros::Rate. We can create an instance of ros::Rate and mention the desired rate that we want. After creating the instance, we have to call the sleep() function inside it to get the rate in effect.

 

The following is an example of getting 10 Hz in C++.

ros::Rate r(10); // 10 hz

r.sleep();
The following is how to do it in Python.
rate = rospy.Rate(10) # 10hz
rate.sleep()
Setting and Getting a ROS Parameter
In C++, we use the following line of code to access a parameter in our code. Basically, we have to declare a variable and use the getParam() function inside the node_handle to access the desired parameter.
std::string global_name;
if (nh.getParam("/global_name", global_name))
{
...
}
The following shows how to set a ROS parameter. The name and the value should be mentioned inside the setParam() function.
nh.setParam("/global_param", 5);
In Python, we can do the same thing using the following line of code.
global_name = rospy.get_param("/global_name")
rospy.set_param('~private_int', '2')

 

The Hello World Example Using ROS

In this section, you are going to create a basic package called hello_world, and a publisher node and a subscriber node to send a “Hello World” string message. You also learn how to write a node in C++ and Python.

 

Creating a hello_world Package

In ROS, the programs organized as packages. So we have to create a ROS package before writing any program. To create a ROS package, we have to give a name of the package, then the dependent packages which help to compile the programs inside the package.

 

For example, if your package has a C++ program, you have to add 'roscpp' as dependency and if it is python, you have to add 'rospy' as a dependency.

 

Before creating the package, first, switch to the class='lazy' data-src folder.

$ catkin_ws/class='lazy' data-src$ catkin_create_pkg hello_world roscpp rospy std_msgs

 

Now we can explore the different files created. The first important file is package.xml. As discussed, this file has information about the package and its dependencies. The package.xml file definition. Actually, when we create the package, it also has some commented code. All comments have been removed here to make it cleaner.

 

You can edit this file and add dependencies, package information, and other information to the package. You can learn more about package.xml at http://wiki.ros.org/catkin/package.xml.

hello

In this file, the minimum version of CMake required to build the package and the project name is at the top of the file.

 

The find_package() finds the necessary dependencies of this package. If these packages are not available, we can’t able to build this package. The catkin_package() is a catkin-provide CMake macro used for specifying catkin-specific information to the build system.

 

You can learn more about CMakeLists.txt at http://wiki.ros.org/ catkin/CMakeLists.txt. 

A good reference for creating a ROS package is at http://wiki.ros.org/ROS/Tutorials/catkin/CreatingPackage.

 

Creating a ROS C++ Node

After creating the package, the next step is to create the ROS nodes. The C++ code is kept in the class='lazy' data-src folder. The following is the first ROS node. It’s a C++ node to publish a “Hello World” string message. You can save it under class='lazy' data-src/talker.cpp.

#include "ros/ros.h"

#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker"); ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_ msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss
<< "hello world " << count; msg.data = ss.str(); ROS_INFO("%s", msg.data.c_str()); chatter_pub.publish(msg); ros::spinOnce()
loop_rate.sleep();
++count;
}
return 0;
}

 

The code is self-explanatory. Basically, it creates a new string message instance and a publisher instance. After creating both, it adds data to the string message along with a count. After adding the data, it publishes the topic, "/chatter. You can also see the usage of the ros::spinOnce() function here. The code executes until you press Ctrl+C.

 

Next, you see the listener.cpp, which subscribes the topic published by talker.cpp. After getting data from the topic, it prints that message.

#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}

 

In listener.cpp, the "chatter" topic is subscribing and registering a callback function for the topic, which is chatterCallback. The callback is defined at the beginning of the code. Whenever a message comes to the "chatter" topic, this callback is executed. Inside the callback, the data in the message is printed.

ros::spin() executes the subscribe callbacks and helps the node remain in a wait state, so it won’t quit until you press Ctrl+C.

Editing the CMakeLists.txt File

After saving the two files in the hello_world/class='lazy' data-src folder, the nodes need to be compiled to create the executable. 

To do this, we have to edit the CMakeLists.txt file, which is not too complicated.

 

We need to add four lines of code to CMakeLists.txt. The figure shows the additional lines of code to insert.

 

You can see that we are adding add_executable() and target_ link_libraries() to CMakeLists.txt. add_executable() creates the executable from the source code. The first parameter is the executable name, which links with the libraries. If these two processes are successful, we get executable nodes.

 

Building C++ Nodes

After saving CMakeLists.txt, we can build the source code. The command to build the nodes is catkin_make. Just switch to the workspace folder and execute the catkin_make command. To switch to the catkin_ws folder, assume that the workspace is in the home folder.

$ cd ~/catkin_ws

 

Executing the catkin_make command to build the nodes $ catkin_make

If everything is correct, you get a message saying that the build was successful. So we have successfully built the nodes. Now what? We can execute these nodes, right? That is covered in the next section.

 

Executing C++ Nodes

  • After building the nodes, the executables are generated inside the catkin_ ws/devel/lib/hello_world/ folder.
  • After creating the executable, we can run it on a Linux terminal.
  • Open three terminals, and execute each command one by one.
Starting roscore

$ roscore

The following command starts the talker node. We can use the rosrun command to start the node.

$ rosrun hello_world talker

The node prints messages on the terminal. Check the list of ROS topics in the system by using the following command.

$ rostopic list

 

You see the following topics.

/chatter

/rosout

/rosout_agg

'chatter is the topic published by the talker node. The /rosout topics are for logging purposes. It starts publishing when we execute the roscore command.

The listener node can start in another terminal.

$ rosrun hello_world listener

 

You can close each terminal by pressing the Ctrl+C key combination. Next, we look at the talker and listener nodes in Python.

 

Creating Python Nodes

We can make a folder called script inside the package, and we can keep the Python scripts inside this folder (scripts/talker.py). The first program that we are going to discuss is http://talker.py.

import rospy
from std_msgs.msg import String
def talker():
rospy.init_node('talker', anonymous=True)
pub = rospy.Publisher('chatter', String, queue_size=10) rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass

 

In the http://talker.py code, in the beginning, we can see, we are importing the rospy module and ros message modules. In the talker() function, we can see the initialization of ROS node, the creation of a new ROS publisher.

 

After initializing the node, we are using a while loop to publish a string message called “Hello World” to the /chatter topic. The working of this node is same as talker.cpp that we already discussed.

 

The subscribing node, called http://listener.py, should be kept inside scripts/ http://listener.py.

import rospy

from std_msgs.msg import String
def callback(data):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
def listener():
#In ROS, nodes are uniquely named. If two nodes with the same
#node are launched, the previous one is kicked off. The
#anonymous=True flag means that rospy will choose a unique
#name for our 'talker' node so that multiple talkers can
#run simultaneously.
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
#spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()

The node is similar to listener.cpp. We are initializing the node and creating a subscriber on the /chatter topic. After subscribing the topic, it waits for ROS messages. The waiting is done with the rospy.spin() function. Inside the callback() function, the message is printed.

 

Executing Python Nodes

Executing Python Nodes

In this section, we see how to execute the nodes. There is no need to compile the Python nodes. We can just execute it using the following commands. You can see the output of the commands.

Start the roscore

$ roscore
Start the http://talker.py
$ rosrun hello_world http://talker.py
Start the http://listener.py
$ rosrun hello_world http://listener.py

 

Creating Launch Files

This section discusses how to write launch files for C++ and Python nodes. The advantage of ROS launch files is that we can run any number of nodes in a single command. We can create a folder called launch inside the package and keep the launch files in that folder.

 

The following is talker_listener.launch, which can run C++ executables.

<launch>
<node name="listener_node" pkg="hello_world" type="listener" output="screen"/>
<node name="talker_node" pkg="hello_world" type="talker" output="screen"/>
</launch>

 

lunch file

This launch file can run the talker and listener nodes in one shot. The package name of the node is in the pkg= field and the name of the executable is in the type= field. You can assign any name to the node.

 

It is better if it is similar to the executable name. After saving the launch file inside the launch folder, you may have to change the permission of the executable.

 

The following shows how to do that.

$ hello_world/launch$ sudo chmod +x talker_listener.launch

The following is the command to execute this launch file. We can execute it from any terminal path.

 

$ roslaunch hello_world talker_listener.launch

After the roslaunch command, use the package name and then the launch file name.

To launch the Python nodes, use the following launch file. You can save it as launch/talker_listener_python.launch.
<launch>
<node name="listener_node" pkg="hello_world" type="http://listener.py" output="screen"/>
<node name="talker_node" pkg="hello_world" type="http://talker.py" output="screen"/>
</launch>
After saving it, change the permissions of the file too.
$ hello_world/launch$ sudo chmod +x talker_listener_python.launch

 

Then execute the launch file using the ros-launch command.

$ roslaunch hello_world talker_listener_python.launch

The output is the same as with the C++ nodes. We can stop the launch file by pressing Ctrl+C in the terminal in which the launch file is running.

 

Visualizing a Computing Graph

Do you want to see what’s happening when the launch files are executing? The rqt_graph GUI tool visualizes the ROS computation graph.

Use any of the launch files that we created in the previous section.

$ roslaunch hello_world talker_listener.launch

And in another terminal, run the following. $ rqt_graph

Visualizing a Computing Graph

In the graph, you see talker_node, which is the name given to talker in the launch file. listener_node is the name of the listener node. /chatter is the topic published by the talker_node. It is subscribed by the listener_node.

 

All the debug messages from these two nodes are going to /rosout. The debug messages are a message that we printed using ROS debug functions (http://wiki.ros.org/roscpp/Over view/Logging). We have already discussed those functions. The /rqt_gui node is also sending debug statements to /rosout.

 

This is how the ROS computation graph works.

Programming turtle using rospy

We are done with the “Hello World” ROS example in C++ and Python. In this section, we use a more interesting application. We saw the turtle application in ROS. Now we look at how to program turtle using rospy Py. We are using rospy for the demo because it is very simple to prototype. In turtles, there is a turtle that we can move around the workspace.

 

Moving turtles

This section discusses how to program the turtle to move around its workspace. You already know how to start the turtle application. The following is the list of commands to run.

Starting roscore

$ roscore
Running turtlesim node in another terminal
$ rosrun turtlesim turtlesim_node
Here is the list of topics which is publishing by turtlesim_node
$ rostopic list
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose

 

To move the turtle inside the turtle application, publish the linear and angular velocity to the /turtle1/cmd_vel topic.

Check the type of the /turtle1/cmd_vel topic by using the following command.
$ rostopic type /turtle1/cmd_vel

geometry_msgs/Twist

This means that the /cmd_vel topic has the geometry_msgs/Twist message type, so we have to publish the same message type to this topic to move the robot. To see the geometry_msgs/Twist definition, use the following command.$ rosmsg show geometry_msgs/Twist

turtle

The twist message has two subsections: linear velocity and angular velocity.

 

If we set the robot’s linear velocity component, it moves forward or backward. In turtles, we can only set the linear.x component because it can move only in the x-direction; there is no motion along y and z. Also, we can set angular.z components to rotate the robot on its axis.

 

There is no effect on other components.

More information about this message is at http://docs.ros.org/api/ geometry_msgs/html/msg/Twist.html.

 

How can we move the topic through the command line? By using rostopic. The following command publishes the linear.x = 0.1 velocity to the turtlenode.

 

Note You don’t need to enter the complete command. Use the Tab key to autocomplete the command. Just type rostopic pub /turtle1/ cmd_vel, and use the Tab key to autocomplete other fields.

$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist "linear:
x:0.1
y:0
z:0
angular:
x:0
y:0
z:0"

 

How do we move the turtle in a Python node?

We are going to create a new node called move_turtle and publish a twisted message to the turtlenode. The figure shows the communication between the two nodes. The following is the code for the move_turtle.py node. You can read the comments in the code to get a better idea about each line of code.

 

#!/usr/bin/env python

import rospy
#Importing Twist message: Used to send velocity to turtlefrom geometry_msgs.msg import Twist
#Handling command line arguments import sys
#Function to move turtle: Linear and angular velocities are arguments
def move_turtle(lin_vel,ang_vel):
rospy.init_node('move_turtle', anonymous=False)
#The /turtle1/cmd_vel is the topic in which we have to send Twist messages
pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10) rate = rospy.Rate(10) # 10hz
#Creating Twist message instance vel = Twist()
while not rospy.is_shutdown():
#Adding linear and angular velocity to the message
vel.linear.x = lin_vel
vel.linear.y = 0
vel.linear.z = 0
vel.angular.x = 0
vel.angular.y = 0
vel.angular.z = ang_vel
rospy.loginfo("Linear Vel = %f: Angular Vel = %f",lin_vel,ang_vel)
#Publishing Twist message
pub.publish(vel)
rate.sleep()
if __name__ == '__main__':
try:
#Providing linear and angular velocity through command line move_turtle(float(sys.argv[1]),float(sys.argv[2]))
except rospy.ROSInterruptException:
pass

 

This code takes the linear and the angular velocity through a command line. We can use the Python sys module to get the command-line arguments inside our code. Once it has the linear velocity and the angular velocity, it calls the move_turtle() function, which inserts both velocities into a twisted message and publishes it.

 

You can save the code as move_turtle.py, and change the permission to executable.

The following shows how to run it.

Start roscore

$ roscore

Start the turtlenode

$ rosrun turtleturtlesim_node

Run the move_turtle.py node along with the command-line arguments, which are 0.2 and 0.1. That is, linear velocity = 0.2 m/s and angular velocity = 0.1 rad/s.

$ rosrun hello_world move_turtle.py 0.2 0.1

 

Printing the Robot’s Position

Printing the Robot’s Position

You have seen how to publish the turtle’s velocity. Now you are going to learn how to get the turtle’s current position from the /turtle1/pose topic. 

Restart turtlesim_node and close move_turtle.py. Echo the /turtle1/ pose topic using rostopic. $ rostopic echo /turtle1/pose

You see the current (x,y, theta) value of the robot and the turtle’s current linear and angular velocities.

 

If you want to get this position in a Python node, you have to subscribe to the called /turtle1/pose topic. To do that and get the data from the message, you have to know the ROS message type. The following finds the message type.

$ rostopic type /turtle1/pose

turtlsim/Pose

If you want to know the message definition, use the following command. $ rosmsg show turtles/Pose

 

As shown in Figure, there are five terms inside the message: x, y, theta, linear velocity, and angular velocity.

To learn more about this message, refer to http://docs.ros.org/api/ turtlesim/html/msg/Pose.html.

 

Let’s modify the existing move_turtle.py and add the option to subscribe to the /turtle1/pose topic. Save this code as move_turtle_get_pose.py. The figure shows how the program works. It is feeding velocity and subscribing the position from the turtlenode at the same time.

move_turtle_get_pose.py code

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
from turtlesim.msg import Pose
import sys
#/turtle1/Pose topic callback
def pose_callback(pose):
rospy.loginfo("Robot X = %f : Y=%f :
Z=%f\n",pose.x,pose.y,pose.theta)
def move_turtle(lin_vel,ang_vel):
rospy.init_node('move_turtle', anonymous=True)
pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
#Creating new subscriber: Topic name= /turtle1/pose:
Callback name: pose_callback rospy.Subscriber('/turtle1/pose',Pose, pose_callback)
rate = rospy.Rate(10) # 10hz
vel = Twist()
while not rospy.is_shutdown():
vel.linear.x = lin_vel
vel.linear.y = 0
vel.linear.z = 0
vel.angular.x = 0
vel.angular.y = 0
vel.angular.z = ang_vel
rospy.loginfo("Linear Vel = %f: Angular Vel = %f",lin_ vel,ang_vel)
pub.publish(vel)
rate.sleep()
if __name__ == '__main__':
try:
move_turtle(float(sys.argv[1]),float(sys.argv[2]))
except rospy.ROSInterruptException:
pass

 

This code is self-explanatory. You can see comments where the code for subscribing the /turtle1/pose topic is added. Run the code by using the following commands. 

 

Starting roscore

$ roscore
Restarting the turtlesim node
$ rosrun turtlesim turtlesim_node
Running move_turtle_get_pose.py code
$ rosrun hello_world move_turtle_get_pose.py 0.2 0.1

 

If we are getting both position and velocity, we can simply command the robot to move to a specific distance, right? The next example is moving the robot with distance feedback. The code is a modification of the move_turtle_get_pose.py code. Moving the Robot with Position Feedback We can save this code as move_distance.py. 

 

Communication of move_distance.py to turtles

This node is simple. We can give linear velocity, angular velocity, and distance (global distance) to it as a command-line argument.

 

Along with publishing velocity to the turtle, it checks the distance moved. When it reaches its destination, the turtle or robot stops. You can read the comments inside the code to understand what's happening inside the code.

#!/usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
from turtlesim.msg import Pose
import sys
robot_x = 0
def pose_callback(pose):
global robot_x
rospy.loginfo("Robot X = %f\n",pose.x)
robot_x = pose.x
def move_turtle(lin_vel,ang_vel,distance):
global robot_x
rospy.init_node('move_turtle', anonymous=True)
pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
rospy.Subscriber('/turtle1/pose',Pose, pose_callback)
rate = rospy.Rate(10) # 10hz
vel = Twist()
while not rospy.is_shutdown():
vel.linear.x = lin_vel
vel.linear.y = 0
vel.linear.z = 0
vel.angular.x = 0
vel.angular.y = 0
vel.angular.z = ang_vel
#rospy.loginfo("Linear Vel = %f: Angular Vel = %f", lin_vel,ang_vel)
#Checking the robot distance is greater than the commanded distance
# If it is greater, stop the node
if(robot_x >= distance):
rospy.loginfo("Robot Reached destination")
rospy.logwarn("Stopping robot")
break
pub.publish(vel)
rate.sleep()
if __name__ == '__main__':
try:
move_turtle(float(sys.argv[1]),float(sys.argv[2]), float(sys.argv[3]))
except rospy.ROSInterruptException:
pass
We can run the code by using the following commands. You can Figure 5-25 for seeing the output
Start roscore
$ roscore
Start turtlenode
$ rosrun turtleturtlesim_node
Run the move_distance.py. Mention linear, angular velocity and the global distance the robot should travel.
$ rosrun hello_world move_distance.py 0.2 0.0 8.0

 

The output of move_distance.py

We have played with a lot of things in turtle using ROS topic. Now, we can work with ROS service and a ROS parameter. The next example simply resets the turtle workspace, and randomly changes the background color.

 

The workspace reset is accomplished using ROS services, and the color changing is done using the ROS parameter. When the workspace resets, the robot’s position resets to the home position and the turtle model changes.

 

Reset and Change the Background Color

This code shows how to call a service and a parameter from a Python code. The following gets the list of services in the turtle node

$ rosservice list

There are several services, but we want the /reset service. When we call this service, the workspace resets.

 

We can retrieve the type of service from the following topic.

$ rosservice type /reset
std_srvs/Empty
std_srvs/Empty is a built-in service from ROS. It has no fields.
The following command shows the field of the corresponding topic.
$ rossrv show std_srvs/Empty

 

We can also list the ROS parameters. You can see the turtle background color in three parameters. If we change these parameters, we change the color. After setting the color, we have to reset the workspace to show the new color.

$ rosparam list

Reset and Change the Background Color

The following gets the value from each parameter.

$ rosparam get /background_b

The following topic publishes the background color.

$ rostopic echo /turtle1/color_sensor

The following code sets the parameter for the background color and resets the workspace by calling /reset service.

#!/usr/bin/env python

import rospy
import random
from std_srvs.srv import Empty
def change_color():
rospy.init_node('change_color', anonymous=True)
#Setting random values from 0-255 in the color parameters rospy.set_param('/background_b',random.randint(0,255)) rospy.set_param('/background_g',random.randint(0,255)) rospy.set_param('/background_r',random.randint(0,255))
#Waiting for service /reset rospy.wait_for_service('/reset')
#Calling /reset service
try:
serv = rospy.ServiceProxy('/reset',Empty)
resp = serv()
rospy.loginfo("Executed service")
except rospy.ServiceException, e:
rospy.loginfo("Service call failed: %s" %e)
rospy.spin()
if __name__ == '__main__':
try:
change_color()
except rospy.ROSInterruptException:
pass
We can save the code as turtle_service_param.py. The following commands starts the ROS node (see Figure 5-29).
Starting roscore
$ roscore
Starting turtlesim_node
$ rosrun turtlesim turtlesim_node
Execute the turtle_service_param.py code
$ rosrun hello_world turtle_service_param.py

 

You have successfully done the turtle exercise. The turtle is actually a robot. You can do all of the operations that you did with the turtle with a physical robot too. The next section explains how to do this operation with an actual robot. It is only a simulation but uses the same procedure as with real hardware.

 

Programming TurtleBot Simulation Using rospy

There are several robots available on the market that run completely on ROS and Ubuntu. The TurtleBot series are low-cost robots that are used for education and research.

 

You can learn more about the TurtleBot 2 robot at www.turtlebot.com/turtlebot2/. If you want to check out the latest version of a TurtleBot, go to http://emanual.robotis.com/docs/ en/platform/turtlebot3/overview/.

 

In this section, we program TurtleBot 2. We look at the installation of TurtleBot 2 packages and how to start the simulation in Gazebo. The code that we developed for turtle works on the TurtleBot 2 and 3 robots. The first step is to install the TurtleBot 2 packages.

 

Installing TurtleBot 2 Packages

The TurtleBot packages are already available in the ROS repository, so we just need to install them. The first step is to update the list of packages by using the following command.

$ sudo apt-get update

 

Installing turtlebot simulation packages

$ sudo apt-get install ros-kinetic-turtlebot-gazebo ros-­ kinetic-turtlebot-simulator ros-kinetic-turtlebot-description ros-kinetic-turtlebot-teleop

These packages install the TurtleBot simulation environment in Ubuntu 16.04 LTS.

 

Launching the TurtleBot Simulation

After installing the TurtleBot packages, launch the simulation of TurtleBot 2 by using the following command.

 

Note It may take time to load the environment in Gazebo. Initially, the Gazebo window may be black because some 3D mesh files are downloading. The time it takes to complete the download depends on your Internet speed. If you feel that Gazebo is stuck, just cancel by pressing Ctrl+C, and launch it again.

 

$ roslaunch turtlebot_gazebo turtlebot_world.launch

This command launches a ROS launch file from the turtlebot_gazebo package. If the simulation loads successfully, you get a window like the one shown in Figure.

 

If you want to move the robot around the environment, start a new terminal and launch the following command.

$ roslaunch turtlebot_teleop keyboard_teleop.launch

When you run this command, you get the following messages on the terminal. Click the terminal using a mouse, and press the keys mentioned on the terminal. You can move the robot using I, J, and L keys.

 

turtle

If you want to stop the robot, press Space bar, if you want to stop the simulation or teleoperation, just press Ctrl+C.

 

Moving a Fixed Distance Using a Python Node

In this section, we move the robot to a fixed distance using the node that we used for turtlesim. We can modify the move_distance.py node.

For turtlebot the velocity Twist message topic is: /cmd_vel_
mux/input/teleop: Message type: geometry_msgs/Twist
Robot position feedback topic: /odom : Message type: nav_msgs/ Odometry

 

We get the definition of odometry from the following command.

$ rosmsg show nav_msgs/Odometry

It is a built-in message type in ROS. We have to import the modules for these messages. The logic of the robot movement is the same as in turtlesim. The distance is global distance. The initial origin of the robot is 0,0,0.

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry
import sys
robot_x = 0
def pose_callback(msg):
global robot_x
#Reading x position from the Odometry message robot_x = msg.pose.pose.position.x
rospy.loginfo("Robot X = %f\n",robot_x)
def move_turtle(lin_vel,ang_vel,distance):
global robot_x
rospy.init_node('move_turtlebot', anonymous=False)
#The Twist topic is /cmd_vel_muc/input/teleop
pub = rospy.Publisher('/cmd_vel_mux/input/teleop', Twist, queue_size=10)
#Position topic is /odom
rospy.Subscriber('/odom',Odometry, pose_callback)
rate = rospy.Rate(10) # 10hz
vel = Twist()
while not rospy.is_shutdown():
vel.linear.x = lin_vel
vel.linear.y = 0
vel.linear.z = 0
vel.angular.x = 0
vel.angular.y = 0
vel.angular.z = ang_vel
#rospy.loginfo("Linear Vel = %f: Angular Vel = %f",lin_ vel,ang_vel)
if(robot_x >= distance):
rospy.loginfo("Robot Reached destination")
rospy.logwarn("Stopping robot")
break
pub.publish(vel)
rate.sleep()
if __name__ == '__main__':
try:
move_turtle(float(sys.argv[1]),float(sys.
argv[2]),float(sys.argv[3]))
except rospy.ROSInterruptException:
pass

 

We can run this code by using the following command.

$ roslaunch turtlebot_gazebo turtlebot_world.launch

Start the TurtleBot simulation. If you are launching a file, you don’t need to start roscore because roslaunch already runs roscore.

Run the move distance node with command-line arguments.

$ rosrun hello_world move_turtlebot.py 0.2 0 3

 

Finding Obstacles

Using the same logic, we can find obstacles around TurtleBot. You can subscribe to the laser scan topic from TurtleBot, which gives the obstacle range around the robot.

Topic: /scan

Message Type: sensor_msgs/LaserScan

Also, you get all the fields inside this message by using the following command.

$ rosmsg show sensor_msgs/LaserScan

 

A good exercise is to create an obstacle avoidance application in ROS.

Programming Embedded Boards Using ROS You have seen how to program a robot in ROS, and you have seen robot simulation. Now let’s discuss how to create robot hardware and program using ROS.

 

One of the core ingredients of a robot is the microcontroller platform. A microcontroller is basically a chip on which we can write our own code. We can also configure the chip’s pins.

 

Microcontrollers are used for various applications. In robotics, controllers are used to interface sensors, such as ultrasonic distance sensors, IR sensors, and so forth, and for adjusting the speed of a robot’s motors. Microcontrollers can also communicate with a PC via serial communication.

 

In this section, you look at some basic interfacing with popular microcontroller platforms, such as the Arduino (www.arduino.cc) and the Tiva-C Launchpad, and with single-­ board computers, such as Raspberry Pi 3 board (www.raspberrypi.org).

Let’s start with the Arduino board.

 

Interfacing Arduino with ROS

arduino

 

Arduino boards are on a microcontroller-based platform that program using a C++–like a programming language. There are a variety of Arduino boards available (www.arduino.cc/en/Main/Products).

 

We are going to use the Arduino Mega, which is available at https://store.arduino.cc/ usa/arduino-mega-2560-rev3. You can program the Arduino board by connecting to your PC. You can download the Arduino IDE from www.arduino.cc/en/Main/Software. When you launch the IDE.

 

In the Arduino programming language, similar to C++, there are a lot of libraries available for simplifying tasks. For example, there are libraries for communicating with a PC, sending speed commands to motor drivers, and so forth.

 

There is also a library for interfacing with ROS. Using this library, the Arduino can send/receive messages to the PC. These messages are converted to topics on the PC side. Arduino can publish data and subscriber data, similar to a ROS node. Actually, Arduino acts like the ROS hardware node

 

First, let’s learn how to create an Arduino library for communicating with the ROS system.

We have to install a ROS package to create this library. The following is the command.

$ sudo apt-get install ros-kinetic-rosserial-arduino

This installs the necessary packages to interface Arduino with ROS.

The next step is to open the Arduino IDE.

Select File Menu ➤ Preference. 

 

arduino

Take a new terminal and switch to sketch post folder path mentioned in the Preference Window. When you switch to this folder, you can find another folder called libraries. You can then switch to the libraries folder and execute the following command.

$ rosrun rosserial_arduino make_libraries.py .

When you run the preceding command, you can see messages print on the terminal. This is actually creating the Arduino library for ROS. After finishing the process, check the libraries folder.

The ros_lib folder is the Arduino library for ROS.

Close the Arduino IDE and restart. 

Then go to File ➤ Examples ➤ ros_ lib. You see a list of examples using Arduino and ROS. 

Let’s discuss a basic example: Blink.

 

Blink is basically a Hello World example for the Arduino. When the Arduino interfaces with ROS, we get a topic. When we publish to a topic, it turns on, and when we publish again, it turns off. It is like LED toggling.

 

The workings of the code is self-explanatory. We create a node and subscribe to a topic called /toggle_led. When a message comes to the topic, the LED turns on, and when the next data comes to the topic, the LED turns off.

 

Let’s upload the code to Arduino. To do that, plug the Arduino to a laptop.

Find the Arduino serial port by using the dmesg command. $ dmesg

 

The Arduino serial device is /dev/ttyACM0.

Change the device’s permission by using the following command.

$ sudo chmod 777 /dev/ttyACM0

 

After that, select this serial device from the Arduino IDE.

Goto Tools->Port->ttyACM0

We can now compile this example and upload the code to the board. After uploading the code, we have to execute the following commands to see the topics from the Arduino. Execute each command in separate terminals.

  • Starting roscore
  • $ roscore

Start the ROS serial server on the PC. The node does the conversion of topics to and from the Arduino.

$ rosrun rosserial_python serial_node.py /dev/ttyACM0

Publish a value to the /toggle_led topic.

$ rostopic pub toggle_led std_msgs/Empty --once

This turns on the LED on the board. If we do it again, it turns off.

 

The LED toggling command

There are more examples of ROS/Arduino interfacing at http://wiki.ros.org/rosserial_arduino/Tutorials.

 

Installing ROS on a Raspberry Pi

The Raspberry Pi computer is a popular board for DIY projects and robotics. The cost of the board is low, and its specifications are best for DIY projects. The latest Raspberry Pi 3 board has the following specs.

Name of SoC: Broadcom BCM2837.
CPU: 4× ARM Cortex-A53, 1.2GHz.
GPU: Broadcom VideoCore IV.
RAM: 1GB LPDDR2 (900 MHz)
Networking: 10/100 Ethernet, 2.4GHz 802.11n wireless.
Bluetooth: Bluetooth 4.1 Classic, Bluetooth Low Energy.
Storage: microSD.
GPIO: 40-pin header, populated.

So how do you install an OS on this board and then install ROS onto it? The next section explains the procedures for installing an operating system and ROS.

 

Burning an Ubuntu Mate Image to a Micro SD Card

To install an OS on the Raspberry Pi 3, you need to buy a micro SD card that is greater than 16 GB. A micro SD card with class 10 is a great choice for the Pi. There is a micro SD card that you can buy at http://a.co/1HyY8qr. You also need to buy a micro SD card reader or an SD card adapter to plug into your laptop.

 

You can install the OS using the following GUI tool.

$ sudo apt-get install gnome-disk-utility

We are going to install Ubuntu Mate on the Raspberry Pi 3. You can download Ubuntu Mate OS from https://ubuntu-mate.org/download/.

 

Choose the Raspberry Pi option from the list. Download the image and open gnome-disk-utility. Select the SD card drive, and select the Restore image option.

You can browse the downloaded image path here. A tutorial is available on YouTube at https://youtu.be/V_6GNyL6Dac.

After completing the restoring process, you can unmount the SD card and plug into the Raspberry Pi 3.

 

Booting to Ubuntu

After plugging in the SD card, plug a 5V, 2A supply to the Raspberry Pi 3, and connect Pi to an HDMI monitor. Also, connect a keyboard and a mouse via USB. The system boots up, and you see the Ubuntu Mate desktop.

 

Installing ROS on a Raspberry Pi

You can follow the ROS installation instructions at http://wiki.ros.org/ kinetic/Installation/Ubuntu. These instructions are the same for the armhf platform, so it works well in Raspberry Pi 3.

 

Summary

This post discussed programming with ROS. We started the post by discussing creating a ROS workspace. We saw how to create a workspace and how to create a ROS package. After creating a package, we saw how to write ROS nodes using C++ and Python. We wrote a sample ROS node using C++ and Python.

 

We discussed ROS launch files and how to include our nodes in a launch file. We created a set of examples to work with turtles in ROS, and we worked with a Gazebo simulation of TurtleBot.

 

At the end of the post, we saw how to program embedded boards such as the Arduino and the Raspberry Pi using ROS, which is very useful when creating robots.

Recommend