An Introduction to Robot Operating System (ROS)

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.

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.

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.

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

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.)

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!