ROS v1: Robot Operating System

Dilip Kumar
8 min readJun 10, 2024

--

What is ROS?

ROS is an open-source framework built for Robotics applications. The goal is to provide standards for robotic software that developers can use and reuse for any robot. The more you will learn about ROS the easier it will be for you to program and understand the code for robots. It also provides many reusable modules to write applications for the robots.

When to use ROS?

Robot programs using Arduino board or custom code with just a sensor and servo motor are very simple to begin with. Slowly more sensors, actuators controllers are added to robots which makes the program complex and a headache to write code to program robot.

ROS helps to develop powerful and scalable robotics applications. It easily manages a lot of communications between subprograms.

ROS big picture

  1. It allows to separation of code into reusable blocks.
  2. Provides a set of tools to easily communicate between sub-programs. This helps to keep separate code and communication tools.
  3. It is language agnostic to allow one part to write in Python and the second part in C++ and both can communicate with each other using ROS communication protocol.

Let’s say to write an application for the robotics arm you can design your code using ROS as below.

  1. Create a sub-program called Node for your camera.
  2. Another sub-program for motion planning.
  3. Another is for hardware drivers.
  4. Another for joystick etc
  5. Use ROS to communicate between these nodes.
  6. ROS provides plug and play libraries to design your app. For example, a library to compute inverse kinematics or plan a trajectory for an arm, etc.

ROS1 vs ROS2

The difference between ROS1 and ROS2 can be categories as below.

Architecture

Changes to the Middleware

  1. ROS 1 uses the ROS Master-Slave Architecture and the XML-RPC middleware. ROS 2 uses Data Distribution Service (DDS), which is designed to provide higher efficiency and reliability, low latency, and scalability, as well as configurable quality of service (QoS) parameters.
  2. XML-RPC is better for simple remote procedure calls, while DDS’s added complexity allows it to better support real-time systems.
  3. Because of its distributed nature, DDS also helps remove communications single points of failure from ROS 2 systems.

Changes to the ROS API

  1. ROS 1 has two separate libraries — roscpp for C++ and rospy for Python — that are not at feature parity with each other.
  2. In contrast, ROS 2 has a base library written in C — rcl (ROS client library) — with libraries built on top of it.
  3. This ensures that core functionality is available in different APIs sooner.
  4. This is one of the key reasons that ROS 2 is able to offer more language support than just Python and C++, such as Java and C#.‍

Changes to the Data Format

  1. ROS2 rosbags allow for more flexibility with regard to serialization as compared to ROS 1, which uses its own serialization format.
  2. The biggest impact of changes to the rosbag format from ROS 1 to ROS 2 is potential incompatibility of ROS 1 bag tooling with ROS 2 rosbags and subsequent impacts to developer workflows.

Features

QoS

  1. ROS 2 allows for data flow configuration, affecting how data is sent and received.
  2. This includes settings for message reliability, deadline, and priority, which can ensure that critical messages are delivered on time.‍

Multi-Threaded Execution

  1. ROS 2 supports multiple nodes truly running in parallel, allowing it to leverage modern multi-core processors far better than ROS 1.‍‍

Real-Time Processing

  1. The summation of the features above, along with the use of DDS, allows ROS 2 to be superior at real-time processing, especially when deterministic, low-latency communication is needed.

Tooling

  1. Catkin is gone, replaced with Ament as a build system
  2. Overlays allow you to have a secondary workspace that doesn’t affect your primary workspace — this is helpful when you want to experiment with new packages without affecting your base configuration (called an “underlay”).‍

Ecosystem

  1. ROS 2 is not backward compatible with ROS 1.
  2. ROS 1 was primarily built for Ubuntu.ROS 2 runs on MacOS, Windows, Ubuntu, and other operating systems.

ROS Nodes

  1. ROS Node is an executable program running inside a robot.
  2. An application can have many nodes which will be put into a package.
  3. The nodes will then communicate with each other.
  4. It reduces code complexity.
  5. Provides fault tolerance on crash of specific node.
  6. Node can be written in any language. Either python or C++.
  7. Two nodes can not have same name.

Hello world ROS Node

import rospy

if __name__ == '__main__':
rospy.init_node('my_first_ros_node')
rospy.loginfo('This node has been started')

rate = rospy.Rate(10)

while not rospy.is_shutdown():
rospy.loginfo('Hello')
rate.sleep()
  1. To start master node run roscore
  2. Start worker node python my_first_ros_node.py
  3. To get the list of running nodes rosnode list
  4. rosout is always running a node for logging and some other functionality.
  5. If you try to start the same node again then the previously running node will be shut down as at a time we can only have one node with the same name.

ROS Commands

  1. To run nodes either written in Python or C++ we can use rosrun command to make it language agnostic.
  2. rosrun <package_name returns the list of either Python or C++ files for the node.
  3. rosrun <package_name> <node_file_name> runs the node.
  4. rosnode info <node_name> to get more details about the node.
  5. rosnode kill <node_name> to stop the running node.
  6. rosnode ping <node_name> to check the health of the running node.

Visualize ROS nodes with rqt

Run rosrun rqt_graph rqt_graph

Learn ROS with turtlesim package

  1. To install sudo apt-get install ros-kinetics-turtlesim
  2. To see a list of nodes with turtlesim run rosrun turtlesim
  3. Run it in the main window rosrun turtlesim turtlesim_node

4. To add key control with turtle rosrun turtlesim turtle_teleop_key . Now you can use arrow key to move turtle.

Here we have two nodes, one for the turtle and a second to capture the keyboard control to move the turtle.

ROS — Topics for communication

Following is one example to showcase the publisher, topic, and subscribers concept.

  1. A topic is the named bus over which nodes exchange messages. Messages are sent over TCP/IP. Nodes are already provided with abstraction to read these messages therefore you don’t have to deal with the lower layer of TCP/IP.
  2. These are unidirectional data streams. Some nodes can publish to the topic and some nodes can subscribe to the topic. There is no response from the subscriber to the publisher. Data is only going one way.
  3. Publishers and subscribers are anonymous to each other.
  4. The topic has a message type. All subscribers and publishers must use a message type associated with the topic.
  5. ROS Topic can be written in Python or C++.
  6. Ros master helps nodes find needed topics. Ros master acts as a DNA server for nodes to find out where to communicate.
  7. A node can have many publishers/subscribers for many different topics.

Publisher example in Python

import rospy
from std_msgs.msg import String

if __name__ == "__main__":
rospy.init_node("robot_news_radio_transmitter")
pub = rospy.Publisher("/robot/news/radio", String, queue_size=10)
rate = rospy.Rate(2)
while not rospy.is_shutdown():
msg = String()
msg.data = "Hi, this radio news 152.5"
pub.publish(msg)
rate.sleep()
rospy.loginfo("Node is stopped")

To view the ros topics list, run rostopic list . To listen to the topic you can run rostopic echo /robot/news/radio to print the incoming messages.

Subscriber example in Python

import rospy
from std_msgs.msg import String

def callback_receive_radio_data(msg):
rospy.loginfo("Message received")
rospy.loginfo(msg)

if __name__ == "__main__":
rospy.init_node("smartphone")
sub = rospy.Subscriber("/robot/news/radio", String, callback_receive_radio_data)
rospy.spin()

ROS Services

  1. ROS Service is a client/server system.
  2. It is synchronous
  3. One message type is for requests and the second type is for responses.
  4. A service server can exist once but can have multiple clients.

Python Service Server

import rospy
from rospy_tutorials.srv import AddTwoInts

def handle_add_two_ints(req):
result = req.a + req.b
rospy.loginfo("Sum of a= "+str(req.a)+" b="+str(req.b)+" is " + str(result))
return result

if __name__ == "__main__":
rospy.init_node("add_two_ints_server")
rospy.loginfo("Add two ints server is created")

service = rospy.Service("/add_two_ints",AddTwoInts, handle_add_two_ints)
service.spin()

We can manually test the service using the command line rosservice call /add_two_ints “a:4 b:5”.

Python Service Client

import rospy
from rospy_tutorials.srv import AddTwoInts

if __name__ == "__main__":
rospy.init_node("add_two_ints_client")
rospy.wait_for_service("/add_two_ints")
try:
add_two_ints = rospy.ServiceProxy("/add_two_ints", AddTwoInts)
response = add_two_ints(2,6)
rospy.loginfo("Sum is " + str(response))
except rospy.ServiceException as e:
rospy.logwarn("Service failed "+str(e))

ROS Message and Service Definition

Two things define a Ros topic

  1. Name, for example/number_count
  2. Message definition, for example std_msgs/int64

Similarly, service is defined by two things.

  1. Name, for example/reset_counter
  2. Service definition, for example std_srvs/SetBool . Definition for request and response.

Message definition is defined once and the build system generates code for Python or C++.

  1. Use primitive types to create message definitions.
  2. You can create a message definition using another message definition.
  3. There are few existing message definitions for example std_msgs , sensor_msgs , geometry_msg etc.
  4. Similarly few existing service definitions for example std_srvs etc.
  5. To learn more about message types, please refer to https://wiki.ros.org/msg

Custom message type

#File name HardwareStats.msg
int64 temperature
bool are_motor_up
string debug_message

Custom service type

#File name ComputeDiskArea.srv
# Request
float64 radious
---
# Response
float64 area

ROS Parameters and Launch files

You would like to use global config to control robot options for example robot name, sensor read frequency, simulation mode, etc.

Ros Parameter Server

It is automatically created inside the ros master server. It is a dictionary and accessible globally from any node.

ROS Launch file

  1. Launch file allows to creation of all nodes with parameters from a single file.
  2. You can also merge multiple launch files to create a single launch file.

Following is a sample launch file for reference.

<launch>
<arg name="port" default="$(optenv HUSKY_PORT /dev/prolific)" />
<node pkg="clearpath_base" type="kinematic_node" name="husky_kinematic" ns="husky">
<param name="port" value="$(arg port)" />
<rosparam>
cmd_fill: True
data:
system_status: 10
safety_status: 10
encoders: 10
differential_speed: 10
differential_output: 10
power_status: 1
</rosparam>
</node>
<!-- Publish diagnostics information from low-level MCU outputs -->
<node pkg="husky_base" name="husky_base_diagnostics" type="diagnostics_publisher" />
<!-- Publish wheel odometry from MCU encoder data -->
<node pkg="husky_base" name="husky_basic_odom" type="basic_odom_publisher" />
<!-- Diagnostic Aggregator -->
<node pkg="diagnostic_aggregator" type="aggregator_node" name="diagnostic_aggregator">
<rosparam command="load" file="$(find husky_base)/config/diagnostics.yaml"/>
</node>
</launch>

Happy Robotics learning :-)

This blog is based on the course https://www.udemy.com/course/ros-for-beginners. The instructor of this course is great, feel free to buy this course to learn more about ROS v1.

--

--

Dilip Kumar
Dilip Kumar

Written by Dilip Kumar

With 18+ years of experience as a software engineer. Enjoy teaching, writing, leading team. Last 4+ years, working at Google as a backend Software Engineer.

No responses yet