rclpy Basics
Introduction
rclpy is the Python client library for ROS 2, providing Python APIs that enable Python programs to communicate with other ROS 2 nodes. This lesson will introduce the fundamental concepts of rclpy, including node creation, parameter management, and basic communication patterns.
What is rclpy?
rclpy is a Python wrapper around the ROS 2 client library (rcl) that provides:
- Node creation and management
- Publisher and subscriber interfaces
- Service and client interfaces
- Action server and client interfaces
- Parameter handling
- Time and timer utilities
- Logging capabilities
Installing rclpy
rclpy comes pre-installed with ROS 2 distributions. You can import it in your Python scripts:
import rclpy
from rclpy.node import Node
Creating Your First Node
Here's a basic example of a node using rclpy:
import rclpy
from rclpy.node import Node
class MyNode(Node):
def __init__(self):
super().__init__('my_node_name')
self.get_logger().info('Hello ROS 2 World!')
def main(args=None):
rclpy.init(args=args)
node = MyNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Node Construction and Destruction
Creating a Node
class MyNode(Node):
def __init__(self):
# Initialize the node with a name
super().__init__('my_node_name')
# Create a parameter descriptor
from rclpy.parameter import Parameter
self.declare_parameter('my_parameter', 'default_value')
# Access the parameter value
my_param = self.get_parameter('my_parameter').value
self.get_logger().info(f'Parameter value: {my_param}')
Proper Node Shutdown
Always ensure proper cleanup:
def main(args=None):
rclpy.init(args=args)
try:
node = MyNode()
rclpy.spin(node)
except KeyboardInterrupt:
node.get_logger().info('Keyboard interrupt received')
finally:
node.destroy_node()
rclpy.shutdown()
Logging with rclpy
rclpy provides built-in logging capabilities:
class MyNode(Node):
def __init__(self):
super().__init__('my_node_name')
# Different log levels
self.get_logger().debug('Debug message')
self.get_logger().info('Info message')
self.get_logger().warn('Warning message')
self.get_logger().error('Error message')
self.get_logger().fatal('Fatal message')
Working with Parameters
Parameters in rclpy allow for configuration of nodes:
class ParameterNode(Node):
def __init__(self):
super().__init__('parameter_node')
# Declare parameters with default values
self.declare_parameter('string_param', 'default_value')
self.declare_parameter('int_param', 42)
self.declare_parameter('double_param', 3.14)
self.declare_parameter('bool_param', True)
# Get parameter values
string_val = self.get_parameter('string_param').value
int_val = self.get_parameter('int_param').value
double_val = self.get_parameter('double_param').value
bool_val = self.get_parameter('bool_param').value
self.get_logger().info(
f'Parameters: {string_val}, {int_val}, {double_val}, {bool_val}'
)
# Callback for parameter changes
self.add_on_set_parameters_callback(self.parameters_callback)
def parameters_callback(self, parameters):
for param in parameters:
self.get_logger().info(f'Parameter {param.name} changed to {param.value}')
return SetParametersResult(successful=True)
Timers in rclpy
Timers allow for periodic execution:
class TimerNode(Node):
def __init__(self):
super().__init__('timer_node')
# Create a timer that fires every 0.5 seconds
self.timer = self.create_timer(0.5, self.timer_callback)
self.counter = 0
def timer_callback(self):
self.get_logger().info(f'Timer callback #{self.counter}')
self.counter += 1
Exception Handling
Proper exception handling is important for robust nodes:
def main(args=None):
rclpy.init(args=args)
node = MyNode()
try:
rclpy.spin(node)
except KeyboardInterrupt:
node.get_logger().info('Node interrupted by user')
except Exception as e:
node.get_logger().error(f'Unhandled exception: {e}')
finally:
node.destroy_node()
rclpy.shutdown()
Best Practices
- Always call
rclpy.init()before creating nodes - Use proper exception handling around
rclpy.spin() - Declare all parameters during node initialization
- Follow naming conventions for nodes, topics, and parameters
- Use logging appropriately to track node state
- Implement proper cleanup with
destroy_node()andrclpy.shutdown()
Summary
rclpy provides the essential tools for developing ROS 2 nodes in Python. Understanding the basics of node creation, parameter management, and proper shutdown procedures is fundamental to building reliable ROS 2 applications. In the next lesson, we'll explore how to bridge Python agents with ROS controllers using rclpy.