Example 1: Nodes
Introduction
Welcome to this ROS1 Noetic tutorial, designed to help you get hands-on experience with creating and managing ROS nodes. In this tutorial, we will build two separate ROS nodes: one that broadcasts the Fibonacci series and another that listens to the broadcasted numbers and prints them. This exercise will give you a foundational understanding of ROS communication mechanisms, specifically publishers and subscribers, within the Robot Operating System (ROS) framework.
ROS (Robot Operating System) is an open-source, flexible framework for writing robot software. It is a collection of tools, libraries, and conventions that aim to simplify the task of creating complex and robust robot behavior across a wide variety of robotic platforms. For a deeper understanding of ROS, you can explore the following resources:
Learning Outcomes
By the end of this tutorial, you will:
- Understand how to set up a ROS workspace.
- Learn how to create and configure ROS packages.
- Write Python scripts for ROS nodes that publish and subscribe to messages.
- Gain practical experience with the ROS communication infrastructure.
Prerequisites
To follow along with this tutorial, you should have:
- Basic knowledge of Python programming.
- ROS Noetic installed on your system. Refer to the ROS Installation Guide for help with setting up ROS Noetic.
Tutorial Structure
-
Setting Up Your ROS Workspace: We’ll start by setting up a new ROS workspace where our packages will reside.
- Creating Packages: Next, we’ll create two packages, one for the broadcaster node and another for the listener node.
- Writing the Broadcaster Node: In this step, we’ll write a Python script that continuously broadcasts the Fibonacci series.
- Writing the Listener Node: Here, we’ll write another Python script that listens for the Fibonacci series and prints each number.
- Configuring Packages: We’ll ensure that our packages are correctly configured by modifying necessary files.
- Building and Running Nodes: Finally, we’ll build our workspace and run the nodes to see them in action.
Few words about ROS Nodes
A node is a fundamental building block in the ROS architecture. Nodes are processes that perform computation and are designed to be modular and reusable. Each node is responsible for a specific task and can communicate with other nodes through a ROS communication system.
Key Characteristics of ROS1 Nodes:
-
Modularity: Nodes are designed to be small, single-purpose executables. This modular approach makes it easier to manage and debug the system.
-
Communication: Nodes communicate with each other using topics, services, and actions.
-
Topics: Used for unidirectional, asynchronous communication where a node publishes messages to a topic, and other nodes subscribe to that topic to receive the messages.
Multi-language Support:
Nodes can be written in various programming languages, such as Python, C++, and Lisp, thanks to the client libraries provided by ROS. This flexibility allows developers to choose the best language for their task.
Outline of a simple ROS1 Node
- Setup: Initialize the ROS client library and create a node handle.
- Define Communication: Define publishers, subscribers, services, or actions as needed.
- Main Loop: Implement the main loop where the node will perform its tasks and handle communication.
Feel free to explore these concepts further through additional resources and community discussions available online.
By the end of this tutorial, you will have created a functional ROS project that demonstrates the basic principles of ROS node communication.
Exercise 1
Step 1: Setting Up The ROS Workspace
First, make sure you have ROS Noetic installed on your system. Then, set up a new ROS workspace:
# Create a new directory for your workspace
mkdir -p ros_workspace/src
cd ros_workspace/src
# Initialize the workspace
catkin_init_workspace
# Go back to the workspace root and build it
cd ros_workspace
catkin_make
Step 2: Create Fibonacci Broadcast Packge
The catkin_create_pkg
takes care of initializing a package for us.
cd ros_workspace/src
# Create the broadcaster package
catkin_create_pkg fibonacci std_msgs rospy
When you run the command catkin_create_pkg
fibonacci std_msgs rospy, it automatically generates a basic package structure for your ROS package. Below is the expected folder structure and a brief description of each component:
ros_workspace/
└──src/
└── fibonacci/
├── CMakeLists.txt
├── package.xml
├── src/
├── include/
├── launch/
└── msg/
Folder and File Descriptions
fibonacci/: The root directory of your package.
CMakeLists.txt
: This file contains CMake directives and macros that are used to build your package. It includes instructions on how to build the package, dependencies, and installation rules.- Key sections:
project()
: Defines the project name.find_package()
: Finds and loads settings for the package dependencies.catkin_package()
: Declares the catkin package and its dependencies.add_executable(), add_library()
: Adds executables and libraries to the project. —
- Key sections:
package.xml
: This file contains meta-information about the package such as its name, version, description, maintainers, license, and most importantly dependencies.- Key sections:
<name>
: Package name.<version>
: Package version.<description>
: Brief description of the package.<maintainer
>`: Maintainers of the package.<license>
: License under which the package is distributed.<build_depend>, <exec_depend>
: Dependencies required to build and run the package. —
- Key sections:
src/
: This directory is intended for the source files of your package, typically containing the node scripts and other implementation files.- Typical contents: Python scripts (e.g.,
fibonacci_broadcaster_node.py
). C++ sources (.cpp
)
- Typical contents: Python scripts (e.g.,
-
include/
: This directory is intended for C++ header files if you have any C++ code in your package.
-
launch/
: This directory is used to store launch files which are XML files that define how to launch one or multiple nodes with specific parameters. This will be used in future exercises.
msg/
: This directory is intended for custom message definitions if you need to define custom message types for your package.- Typical contents: Message files (e.g., Fibonacci.msg).
This structured organization helps manage the package efficiently, ensuring that all necessary components are properly placed and accessible for development and execution within the ROS framework.
Step 3: Write the Fibonacci Broadcaster Node
Navigate to the fibonacci package and create a new Python script:
cd ros_workspace/src/fibonacci/src
touch fibonacci_broadcaster_node.py
chmod +x fibonacci_broadcaster_node.py
Open fibonacci_broadcaster_node.py
and add the following code:
#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
def fibonacci():
pub = rospy.Publisher('fibonacci', Int32, queue_size=10)
rospy.init_node('fibonacci_broadcaster', anonymous=True)
rate = rospy.Rate(1) # 1 Hz
a, b = 0, 1
while not rospy.is_shutdown():
rospy.loginfo(a)
pub.publish(a)
a, b = b, a + b
rate.sleep()
if __name__ == '__main__':
try:
fibonacci()
except rospy.ROSInterruptException:
pass
Step 4: Modify the CmakeLists.txt
and package.xml
Everytime we create a package, ensure the CMakeLists.txt and package.xml are correctly set up to include dependencies and scripts.
In the fibonacci
folder, edit CmakeLists.txt
to add:
catkin_install_python(PROGRAMS src/fibonacci_broadcaster_node.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
Add these lines in the middle of package.xml
to ensure it includes the dependency on rospy
and std_msgs
:
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
Step 5: Build and Source the Broadcaster
Go back to the root of your workspace and build it:
#dont forget to input the correct path here
cd ros_workspace
catkin_make
source devel/setup.bash
sourcing devel/setup.bash
in the current terminal tells bash where to look for the binaries we created by building the package when we want to run them. You need to do this everytime you opena new terminal where you want to run something from your workspace. Think of it as we are adding to the PATH
environment variable in windows temporarely.
Step 6: Run the Broadcaster
Open three terminals and source your workspace (and ros workspace) in all of them.
#dont forget to input the correct path here
cd ros_workspace
source /opt/ros/noetic/setup.bash
source devel/setup.bash
In the first terminal, run the roscore
to start a ROS master
roscore
In the second terminal, run the broadcaster node:
rosrun fibonacci fibonacci_broadcaster_node.py
You can now in the third terminal verify that the node is running by listing the nodes using rosnode list
. You can also verify if the topic we created to publish the fibonacci numbers exists by running rostopic list
.
Exercise 2
Now we will create a subscription node that will listen to the fibonacci numbers and print them to the terminal.
Step 1: Create a Listener Node
Navigate to the fibonacci package and create a new Python script:
cd ros_workspace/src/fibonacci/src
touch fibonacci_listener_node.py
chmod +x fibonacci_listener_node.py
Open fibonacci_listener_node.py
and add the following code:
#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
def callback(data):
rospy.loginfo("I heard %d", data.data)
def listener():
rospy.init_node('fibonacci_listener', anonymous=True)
rospy.Subscriber('fibonacci', Int32, callback)
rospy.spin()
if __name__ == '__main__':
listener()
Step 2: Edit the package files
In the fibonacci
folder, edit CmakeLists.txt
to add:
catkin_install_python(PROGRAMS src/fibonacci_broadcaster_node.py
src/fibonacci_listener_node.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
Step 3: Build and source
Go back to the root of your workspace and build it:
cd ros_workspace
catkin_make
source devel/setup.bash
Step 4: Run the packages side-by-side
Open two terminals and source your workspace in both:
source ros_workspace/devel/setup.bash
In the first terminal, run the broadcaster node
rosrun fibonacci_broadcaster fibonacci_broadcaster_node.py
In the second terminal, run the listener node
rosrun fibonacci_listener fibonacci_listener_node.py
You should see the Fibonacci series being printed by the listener node, which receives the numbers from the broadcaster node.
Step 5: View the relationship using rqt
Open a third terminal and source your workspace and the ros sources /opt/ros/noetic/setup.bash
.
Run rqt using the command rqt
, then go to the plugins tab, navigate to introspection, then visualize the nodes and topics.