Lab Exercise 1: Basic Node Communication in ROS 2
Objective
In this lab exercise, you will create and run a simple publisher-subscriber system in ROS 2 to understand the fundamental concepts of node communication.
Learning Objectives
After completing this lab, you will be able to:
- Create a ROS 2 package for your project
- Implement a publisher node that sends custom messages
- Implement a subscriber node that receives and processes messages
- Launch and test your publisher-subscriber system
- Use ROS 2 command-line tools to inspect your nodes
Prerequisites
- ROS 2 installation (Humble Hawksbill or later)
- Basic Python programming knowledge
- Understanding of ROS 2 concepts (covered in Week 1-2 content)
Equipment Required
- Computer with ROS 2 installed
- Terminal/shell access
- Text editor or IDE
Lab Steps
Step 1: Create a ROS 2 Package
-
Create a new workspace directory:
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src -
Create a new ROS 2 package called
robot_basics_lab:ros2 pkg create --build-type ament_python robot_basics_lab -
Navigate to the package directory:
cd robot_basics_lab
Step 2: Create the Publisher Node
-
Create a directory for your Python scripts:
mkdir robot_basics_lab
cd robot_basics_lab -
Create a file called
talker.pywith the following content:import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class TalkerNode(Node):
def __init__(self):
super().__init__('talker')
self.publisher_ = self.create_publisher(String, 'chatter', 10)
timer_period = 0.5 # seconds
self.timer = self.create_timer(timer_period, self.timer_callback)
self.i = 0
def timer_callback(self):
msg = String()
msg.data = f'Hello World: {self.i}'
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing: "{msg.data}"')
self.i += 1
def main(args=None):
rclpy.init(args=args)
talker = TalkerNode()
rclpy.spin(talker)
talker.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Step 3: Create the Subscriber Node
- Create a file called
listener.pywith the following content:import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class ListenerNode(Node):
def __init__(self):
super().__init__('listener')
self.subscription = self.create_subscription(
String,
'chatter',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
self.get_logger().info(f'I heard: "{msg.data}"')
def main(args=None):
rclpy.init(args=args)
listener = ListenerNode()
rclpy.spin(listener)
listener.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Step 4: Make Scripts Executable and Configure Setup
-
Go back to the package root:
cd ~/ros2_ws/src/robot_basics_lab -
Make the Python files executable:
chmod +x robot_basics_lab/talker.py
chmod +x robot_basics_lab/listener.py -
Edit the
setup.pyfile to add entry points for your scripts:import os
from glob import glob
from setuptools import setup
package_name = 'robot_basics_lab'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='Your Name',
maintainer_email='your.email@example.com',
description='Robot Basics Lab for ROS 2',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'talker = robot_basics_lab.talker:main',
'listener = robot_basics_lab.listener:main',
],
},
)
Step 5: Build and Test Your Package
-
Go to your workspace root directory:
cd ~/ros2_ws -
Build your package:
colcon build --packages-select robot_basics_lab -
Source the setup file:
source install/setup.bash
Step 6: Run Your Publisher-Subscriber System
-
In one terminal, run the publisher:
ros2 run robot_basics_lab talker -
In another terminal (remember to source setup again), run the subscriber:
ros2 run robot_basics_lab listener -
Observe the messages being published and received.
Step 7: Explore with ROS 2 Tools
-
In a third terminal, list active nodes:
ros2 node list -
Check the topics being used:
ros2 topic list -
Echo the chatter topic to see the messages:
ros2 topic echo /chatter
Expected Results
- The talker node should publish "Hello World" messages to the
/chattertopic every 0.5 seconds - The listener node should receive and print these messages to the terminal
- You should be able to use ROS 2 tools to inspect the nodes and topics in your system
Troubleshooting
- If you get "command not found" errors, ensure ROS 2 is sourced in your terminal
- If nodes can't communicate, check that they're on the same ROS_DOMAIN_ID
- If the build fails, check that all dependencies are properly declared in your package.xml
Extension Activities
- Modify the publisher to send different types of messages (integers, floats)
- Add a second publisher or subscriber to your system
- Experiment with different Quality of Service (QoS) settings
Assessment Questions
- What is the purpose of the
create_publishermethod? - How does the timer callback work in the publisher node?
- Why do we need to call
rclpy.spin()in the main function? - What would happen if you changed the timer period to 2 seconds?
Summary
This lab introduced you to creating basic ROS 2 nodes for communication. You've successfully implemented a publisher-subscriber pattern, which is one of the fundamental communication methods in ROS 2.