Technical Article

An Introduction to Robot Operating System (ROS)

June 26, 2017 by Yahya Tawil

Developing a robot with a computer brain needs a bunch of software tools on the computer side—like software drivers, third party tools for computer vision, simulation tools, and more. ROS framework gathers all these tools and manages how you develop a code for your robot.

Developing a robot with a computer brain requires a bunch of software tools on the computer side—like software drivers, third party tools for computer vision and simulation tools. ROS framework gathers all these tools and manages how you develop a code for your robot.

Instead of reinventing the wheel every time, some frameworks can help you by gathering all these tools and managing how you develop code for your robot. ROS (Robot Operating System) is one of these frameworks. It’s a special framework initially developed by the Stanford AI Laboratory in 2007 for developing robots. The Open Source Robotics Foundation now maintains ROS.

The concept of ROS goes far beyond just a framework. ROS is an OS in concept because it provides all the services that any other OS does—like hardware abstraction, low-level device control, implementation of commonly-used functionality, message-passing between processes, and package management. Even though ROS is still a framework that isn't a standalone OS or an RTOS and isn't the only framework for robots, it seems to be adopted widely and have a large developers community.

ROS can be installed on a single-board computer (SBC) like Raspberry Pi-level and upwards with Ubuntu/Debian distro. However, other platforms are supported experimentally or by the community.

 

ROS Logo

An Overview of How ROS Works

Before we go deeper and start playing with ROS, we need to see the big-picture of the system.

In general, ROS consists of code and tools that help your project's code run and do the required job—including the infrastructure for running it, like messages passing between processes.

ROS is designed to be a loosely coupled system where a process is called a node and every node should be responsible for one task. Nodes communicate with each other using messages passing via logical channels called topics. Each node can send or get data from the other node using the publish/subscribe model. We are going to see that in action later.

The primary goal of ROS is to support code reuse in robotics research and development so you can find a built-in package system. Again, keep in mind that ROS is not an OS, a library, or an RTOS. It’s a framework using the concept of an OS.

 

Nodes and topics. Image adapted from a tutorial from Justin Huang.

Installation and First Test

ROS supports machines that run Linux with Ubuntu or Debian distro. It has a lot of releases with names ordered alphabetically. In this article, we are going to install the Kinetic edition.

 

ROS versions

ROS versions. Image courtesy of Wikipedia.

 

Now, follow the instructions below to install ROS:

  • Add the ROS sources to APT:

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

 

  • Add ROS keys

$ sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116

 

  • Update the APT sources

$ sudo apt-get update

 

  • Install ROS

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

 

  • rosdep is a command-line tool for installing system dependencies and it needs to be initialized only once after installation

$ sudo rosdep init
$ rosdep update

 

  • In order to use built-in ROS commands, we need to add these to the bash session each time a new shell is launched

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

 

  • For a one time change

$ source /opt/ros/kinetic/setup.bash

 

Turtlebot Example: Running a Gazebo Simulation Environment

As a small test, we will run a simulation environment called Gazebo for a Turtlebot robot.

 

Turtulebot

The Turtlebot. Image courtesy of Willow Garage.

 

Gazebo Environment

 

To install Gazebo, run the following in the terminal:

$ sudo apt-get install ros-Kinetic-turtlebot ros-indigo-turtlebot-apps ros-Kinetic-turtlebot-interactions ros-Kinetic-turtlebot-simulator ros-Kinetic-kobuki-ftdi ros-Kinetic-ar-track-alvar-msgs

 

After installation is complete, type the following:

$ roslaunch turtlebot_gazebo turtlebot_world.launch

 

Wait for a little and the simulator should start working.

 

Gazebo enviroment

 

Now let’s do the first exciting thing: Let’s control the robot from the keyboard. Open a new instance of the terminal and run the following:

$ roslaunch turtlebot_teleop keyboard_teleop.launch

 

 

Now you can move the robot using the keyboard.

Congratulations! ROS is now installed and working properly!

A Deeper View of How ROS Works

Before writing our first code, let’s take a deeper dive into understanding how ROS works. We will examine some concepts using the Gazebo example.

As we said in the overview, nodes are the processes that perform tasks. However, ROS has a command-line tool called Rosnode, which can be used to show the active nodes in a running system. The Rosnode list command will list them. Let’s list the nodes in our example while turtlebot_teleop is running. The output will look something like:

/bumper2pointcloud

/cmd_vel_mux

/depthimage_to_laserscan

/gazebo

/laserscan_nodelet_manager

/mobile_base_nodelet_manager

/robot_state_publisher

/rosout

 

 

 

In order to manage this loosely-coupled environment, there is a Master in ROS which is responsible for name registration and lookup for the rest of the system. Without the Master, nodes would not be able to find each other or exchange messages. To start the Master you should issue roscore or roslaunch.

 

Master in ROS. Image adapted from a tutorial from Justin Huang.

 

Back to messages. Messages are structs of data filled with pieces of information by nodes. Nodes exchange them using what’s called topics (logical connection paths), then nodes either publish topics or subscribe to them.

Respectively, rostopic command-line tool can be used to list topics. Let’s see what are the available topics in this example by using rostopic list command. The output will be something like this:

 

 

One of the topics called is /cmd_vel_mux/input/teleop and it’s published by turtlebot_teleop. To be sure of this information, we will run rostopic info /cmd_vel_mux/input/teleop.

 

 

As we can see, the type of messages exchanged by it are called geometry_msgs/Twist. We will use rosmsg show geometry_msgs/Twist to learn more about this data structure.

geometry_msgs/Vector3 linear

 float64 x

 float64 y

 float64 z

geometry_msgs/Vector3 angular

 float64 x

 float64 y

 float64 z

 

ROS uses a simplified messages description language for describing the data fields in messages. You can refer to the ROS documentation website to know more about the description language.

Turtlebot_teleop is called a package in ROS. Packages are the main units for organizing software in ROS and may contain nodes, an ROS-dependent library, datasets, configuration files and others. You can browse the turtlebot_teleop package in /opt/ros/kinetic/share/turtlebot_teleop. To find out where ROS is installed, you can use the which command.

$ which rosnode
/opt/ros/kinetic/bin/rosnode

 

Last but not least, You can write your code in Python, C++ or Lisp. Moreover, ROS also has experimental libraries for other languages like Java.

Having several abstraction levels in ROS gives you the flexibility to write your nodes in different languages for the same system; this definitely will help with more collaboration and code reusability.

We’ve looked at the basic concepts behind ROS for a start but, to be honest, there are many more concepts to look over on the ROS documentation website. In this introductory article, these basic concepts are enough to write your first node. However, more concepts can be explored in a follow-up article.
 

Build Up Your First Node

An odom topic in the Gazebo environment contains the position of Turtlebot. We are going to write our first node which simply subscribes to the /odom topic and prints the position on the terminal.

ROS uses catkin as the build system. While catkin is not our interest here, you can read a conceptual overview about catkin to familiar 

You must install catkin first:

$ sudo apt-get install ros-kinetic-catkin

 

...and the dependencies:

$ sudo apt-get install cmake python-catkin-pkg python-empy python-nose python-setuptools libgtest-dev build-essential

 

After installing catkin, we need to create a workspace in the home directory:

$ mkdir -p ~/catkin_ws/src

 

Let’s create a package to write inside our first node. We will call it location_monitor. Catkin has a tool to create packages with parameters including package name and dependencies:

$ cd catkin_ws/src/
$ catkin_create_pkg location_monitor std_msgs rospy roscpp

 

Before starting to write the code, we need to know the message type of /odom:

$ rostopic info /odom

Type: nav_msgs/Odometry

Publishers:

* /gazebo (http://yahya-Compaq-Presario-CQ61-Notebook-PC:37411/)

 

Subscribers: None

 

To know what Nav_msgs/Odometry contains, run rosmsg show nav_msgs/Odometry. To write the code, we will create location_monitor.cpp:

$ cd catkin_ws/src/location_monito/src/
$ gedit location_monitor.cpp

//location_monitor.cpp
//Original Author: Justin Huang
#include "ros/ros.h"
#include "nav_msgs/Odometry.h"

void OdomCallback(const nav_msgs::Odometry::ConstPtr& msg)
{
double x = msg->pose.pose.position.x;
double y = msg->pose.pose.position.y;
ROS_INFO("x: %f, y: %f", x, y);
}

int main(int argc,char** argv)
{
ros::init(argc, argv, "location_monitor");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("odom", 10, OdomCallback);
ros::spin();
return 0;
}


Let's break the code down.

 

ros::init(argc, argv, "location_monitor");

The above initializes ROS and allows ROS to do name remapping for our node “location_monitor”. The name should be unique in a running system.

 

ros::NodeHandle nh;

This creates a handle to this process's node.

 

ros::Subscriber sub = nh.subscribe("odom", 10, OdomCallback);

This subscribes to the odom topic. ROS will call the OdomCallback() function whenever a new message arrives. The second argument is the queue size (10 messages).

 

ros::spin();

This waits for messages to arrive. When a message arrives, the OdomCallback() function will be called.

 

void OdomCallback(const nav_msgs::Odometry::ConstPtr& msg)

{

double x = msg->pose.pose.position.x;

double y = msg->pose.pose.position.y;

ROS_INFO("x: %f, y: %f", x, y);

}

msg has the type nav_msgs/Odometry as we saw from running rostopic info /odom. While ROS_INFO is one of built-in printing functions.


The last step before building the project is to open catkin_ws/src/location_monitor/CMakeLists.txt and change its contents to add location_monitor.cpp as an executable target that must be built and to add nav_msgs to dependencies. (Refer to CmakeLists documentation page for more on this.)

# %Tag(FULLTEXT)%
cmake_minimum_required(VERSION 2.8.3)
project(location_monitor)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs nav_msgs)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs nav_msgs)

## Declare a catkin package
catkin_package()

## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(location_monitor src/location_monitor.cpp)
target_link_libraries(location_monitor ${catkin_LIBRARIES})
add_dependencies(location_monitor location_monitor_generate_messages_cpp)


# %EndTag(FULLTEXT)%


Now it’s time to build our project. First, go back to catkin_ws:

$ cd ~/catkin_ws

 

Then build the project:

$ catkin_make

 

And the last important thing to do is to update your bash session with the new package “location_monitor”:

$ source devel/setup.bash

 

To run the new node, we need to run Gazebo first because Gazebo is the publisher and Location_monitor is the subscriber:

$ roslaunch turtlebot_gazebo turtlebot_world.launch

 

Then run the “location monitor” node:

$ rosrun location_monitor location_monitor

 

The screenshot below represents the output (you can run keyboard_teleop to see the position value changing):

 

Further Reading

This has been just an introduction to ROS. There are many tools and concepts that need to be learned using formal step by step ROS tutorials.

I hope that you're inspired to consider using ROS in you next microcontroller/Arduino robotic project using a serial interface between the microcontroller/Arduino and ROS master.

Don't miss the chance to preview the list of Robots with ROS inside in lots of application fields to give you some ideas!

If you'd like more articles on ROS, let us know in the comments.

2 Comments
  • R
    reboot_man June 28, 2017

    Hey, thank you for such a great post!! I recently installed ROS Indigo on my RPi 3 and wanted to know if it is possible to install and run Gazeebo on a RPi? Also would you know any good books to start out on ROS for beginners? All I’ve done till now is worked with Arduino, a bit with Pi. I really want to get started with building robots with ROS. Thanks! 😊

    Like. Reply
    • Yahya Tawil June 28, 2017
      Actually, I didn't test Gazebo on a RPi. But I think it's a heavy simulation program, and even if it worked, Gazebo probably consumes all of RPi resources, but I think it worth a try!. About books, You can see the list of books about ROS in their wiki page: http://wiki.ros.org/Books Best, Yahya
      Like. Reply