An Intuitive Guide to Robot Operating System (ROS)

In robotics, where precision and synchronization are paramount, the ability to coordinate activities across distributed nodes is crucial. Robot Operating System (ROS), a middleware framework for robotic software development, provides a powerful mechanism for achieving temporal harmony through the use of ROS topics. Moreover, ROS helps a smooth and reliable communication between software and hardware. For instance, one can write a small program that reads image data from a particular camera and can declare that code as camera-node. After some processing, another code can be created that sends some command signal to a motor. This can be called motor-node. Hence, by developing nodes as per usability, the Robot Operating System allows robust, yet simple communication between sensors and actuators. This communication takes place through transferring information via topics.

Why should we use ROS anyway?

During my thesis, I had a task of using two cameras as one stereo camera to measure the distance of an object. If your are familiar with stereo cameras, you might know that it is necessary calibrate the cameras so that they can measure the distance of objects correctly. Now to accomplish camera calibration, one would traditionally have to write couple of lines of code, maybe debug and rectify the errors, and then would have the result. This still consumes time and energy. But ROS provides a library called camera_calibration with the help of which, I saved significant amount of time and saved myself from the stress of writing the code and debugging it. Hence, there are many ROS libraries that you can use and save yourself from writing the code that someone else has already done.

Moreover, ROS enables easy communication. Again I am going to share a real experience. While working on a project related to self-driving cars, we have 2 working stations in the vehicle. Now the first station was responsible for collecting sensor data and the other one was meant to do the computation work. Hence, building a TCP or UDP connection between them would take a significant amount of time. More importantly, you also need to take care of the data type that you are sharing. With ROS, I just needed to publish my data as a topic from one station and subscribe to that topic from the other one.

If all of these still sound unclear and overwhelming, let us start by doing a small project where you will publish the current time as a ROS topic.

robot operating system
Photo by Pixabay on Pexels.com

Publishing Current Time using ROS

To illustrate the functionality of ROS topics, let’s explore a practical ROS example in Python. The goal is to create a ROS node that publishes the current time as a message on a custom ROS topic. This example demonstrates the simplicity and effectiveness of leveraging ROS topics for reliable communication.

[Before we get started with coding, it is assumed that you are working in Ubuntu/Linux OS. Moreover, you should have ROS installed in your system. If not, click here to install it.]

Step 1: Set Up Your ROS Workspace

Ensure that you have a working ROS installation and an initialized catkin workspace. If you don’t have one, create a ROS workspace as follows:

mkdir -p ~/ros_ws/src

Step 2: Create a ROS Package

Inside your workspace, create a new ROS package. Navigate to the ‘src’ directory and execute:

cd ~/ros_ws/src
source /opt/ros/noetic/setup.bash
catkin_create_pkg time_publisher rospy std_msgs

This command creates a ROS package named time_publisher with dependencies on rospy (ROS Python library) and std_msgs (standard ROS messages). If you look into the time_publisher folder, you’ll find the ‘CMakeLists.txt’ and the ‘package.xml’ files. Keep a note of them as we will need them later.

Step 3: Create a ROS node

Create a Python script within the ‘src’ directory of your package, e.g., ‘current_time_publisher.py’. Copy the following code and paste it in that Python file:

#!/usr/bin/env python

import rospy
from std_msgs.msg import String
from datetime import datetime

def publish_current_time():
    # Initialize the ROS node
    rospy.init_node('current_time_publisher', anonymous=True)

    # Create a ROS publisher for the "/current_time" topic
    current_time_publisher = rospy.Publisher('/current_time', String, queue_size=10)

    # Set the publishing rate (e.g., every 1 second)
    rate = rospy.Rate(1)

    # Main loop
    while not rospy.is_shutdown():
        # Get the current time
        current_time = str(datetime.now())

        # Publish the current time to the "/current_time" topic
        current_time_publisher.publish(current_time)

        # Log the published time for debugging purposes
        rospy.loginfo(f"Published current time: {current_time}")

        # Wait until the next publishing cycle
        rate.sleep()

if __name__ == '__main__':
    try:
        publish_current_time()
    except rospy.ROSInterruptException:
        pass

The rospy.Publisher class facilitates the creation of a publisher for the specified topic, and the loop ensures that the current time is continually published. The rest of the explanation is provided in the comments in the script.

Step 4: Make the Script Executable and describe it in CMakeLists.txt

Navigate to the ‘src’ directory and make the script executable:

sudo chmod +x current_time_publisher.py

CMakeLists.txt is a file that is used for building a project. In our ROS package, after making the file executable, it is necessary to let CMakeLists.txt know what and where our source file is. Open the CMakeLists.txt of your ROS package and edit the catkin_install_python() function:

catkin_install_python(PROGRAMS
src/current_time_publisher.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

Step 5: Build and Source Your Workspace

Return to the root of your ROS workspace and build your package:

cd ~/ros_ws
catkin_make

After the build is successful, we need to source the setup file of our ROS environment. After a successful build, two new folders are generated: build and devel. The source file is located in the devel folder.

source devel/setup.bash

Step 6: Run the ROS Node

Before running the ROS node, it is necessary to start the ROS server:

roscore

In a different terminal, source the setup file of the workspace again and run the node:

cd ~/ros_ws/
source devel/setup.bash
rosrun time_publisher current_time_publisher

Step 7: Observe the Published Current Time

Open a new terminal and subscribe to the ‘/current_time’ topic:

ros topic echo /current_time

You will now see the current time being published on the ‘/current_time’ topic at the specified rate.

Conclusion

In this exercise, we created a node and published the current_time topic. But this was just a teaser. With the fundamentals of Robot Operating System that we learned in this exercise, we will next create a ROS package where we will publish the information we collect from a GPS sensor. Make sure that you first understand how to collect coordinates using Python, as we will be using the code from that project. Stay tuned and happy coding 🙂

Your little support gives me the motivation to create interesting and fun content. All you have to do is follow me on my social media :):

Leave a Reply