Congratulations, you have now successfully configured ROS for your target system. It’s time to get to know the fundamental features of ROS. There are two main styles of development in ROS - we can either write everything from scratch, which for a small application is doable, but defeats the purpose of using ROS when we apply this for a large(complex) system. We will focus on the first approach here.

The “chatter” application

The chatter is almost like the “Hello World” of the ROS universe. It is the most basic application we can have that makes use of the capabilities of ROS. It will be a very simple application, which will make use of ros messages to communicate over a ros topic using ros nodes. These need to be defined first:

  • A ROS node is an executable that uses ROS to communicate with other nodes in a network. For our purpose, we can look at it just like a simple executable.

  • A ROS topic is the data channel through which the ROS nodes communicate with each other.

  • A ROS message defines the type of data that is flowing through the channel.

Now that these definitions are in place, we would want to go ahead and implement a simple Publisher-Subscriber application. There will be two nodes, conveniently named “publish” and “subscribe”, which will exchange a string message over a topic called “/chatter”. The graph for the application can be seen below:

NOTE: This tutorial is going to be a gross oversimplication of creating a simple ROS application, as the explanations of core ROS functionalities is beyond the scope. For a detailed tutorial with individual focus on each module, we invite you to check out the ROS Wiki.

We navigate to the src directory of our catkin workspace that we had created after the ROS installation. It is located in ~/ros/src for the purpose of the tutorial. There we have to build a package, which is facilitated by using catkin_create_pkg utility. The standard format for creating a catking package using this tool is:

catkin_create_pkg <name_of_package> <depends1> <depends2> ... <dependsn>

So here we see that we have to specify the name of the package and add the names of other packages that our package depends on. Let us call our package “chatter” and since we will only be sending a string message, we know that our package will depend on the std_msgs package. Also, we will need the roscpp and the rospy dependencies.

So, the command we should type in our terminal should be as follows:

cd ~/ros/src
catkin_create_pkg chatter std_msgs roscpp rospy
catkin build && exit

So we have generated and built our package, now it is time to put some code in it. Open up a new terminal and navigate to your ROS package using roscd. Using roscd allows you to directly navigate to the src directory of the package. In order to cd into our chatter package, we will type roscd chatter. Use the Tab key to autocomplete and also check if it is properly configured or not.

Now we will store all the source files in the src directory. We will create two files, a publisher.cpp and a subscriber.py file, just to illustrate the ROS development policy.

Writing a ROS publisher node

ROS topics use a publish-subscribe model of communication between themselves. In order to send data over to some other ROS node, we have to write a ROS publisher. The required bit of code is given below:

#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 chat_pub = n.advertise<std_msgs::String>("chatter", 1);
	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());

		chat_pub.publish(msg);

		loop_rate.sleep();
	}
	return 0;
}

What we are essentially trying to do here is set up a simple publisher of type std_msgs/String that will publish the String “Hello world” along with the current value of the variable count to the “chatter” topic. A subscriber will subscribe to this topic and extract the data from this stream. The code for the subscriber is given below:

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)

def listener():
    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()

After we are done writing our code, we have the let CMake know about the executables we want to create. This can be done very easily if you make the following changes in your CMakeLists.txt file:

cmake_minimum_required(VERSION 3.0.2)
project(chatter)

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)

catkin_package()
include_directories(${catkin_INCLUDE_DIRS})

add_executable(talker src/publisher.cpp)
add_dependencies(talker ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(talker ${catkin_LIBRARIES})

catkin_install_python(PROGRAMS scripts/subscriber.py
 DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

This marks the end of all the code we need to write. Now, open up a terminal, navigate to your ros workspace, and build it:

cd ~/ros && catkin build

If everything is built successfully, you should get a message saying “Build succeeded”. Now it is time to launch our ROS application.

Launching the ROS application

Once our package is built, now we can go ahead and run the application. You want to spawn four empty terminals, and designate one task to each terminal. That way, it becomes easier to organise yourself in a ROS developement environment.

  • In the first empty terminal, you would want to run the ROS master. This ROS master will be responsible for connecting all the nodes as required. This can be done by simply running the command roscore on the terminal. After running this command, the terminal should look like the following:

NOTE: This terminal will be used only for interacting with the ROS master. As you will see if you try to type in this terminal, nothing happens. This is because the program is still executing.

  • In the second empty terminal, we will run the talker node. The format we follow while running a ROS node is : rosrun <package_name> <node_name>. So, for our case this will be
    rosrun chatter talker
    

    Once again, if it autocompletes by pressing Tab, you are on the right track. This will make the talker node start publishing the streams of “Hello World” and an incrementing number count. This should produce something like the following:

  • In the third terminal, we want to run the listener node, so that we can listen to what the publisher is publishing. Like before, you can type the following command to run the listener node:
    rosrun chatter listener.py
    

    This will produce something like the following image:

Now that we have successfully built our first ROS application, we can go on to include more functionalities and design of our next application.