This document provides a Python code example for adding parameters to a ROS 2 node, including setting a default value and descriptor, and resetting the parameter to its default value. The document also includes instructions for adding an entry point and building and running the code, as well as a GIF demonstrating how to change the parameter value.

<aside> 💡 When making your own nodes, you will sometimes need to add parameters that can be set from the launch file. Parameters are set inside the Python class definition.

</aside>

1. Write the Python node

parameter1.mp4

Inside the humble_ws/src/ros_basics/ros_basics directory, create a new file called python_parameters_node.py and paste the following code within:

import rclpy
from rclpy.node import Node

class MinimalParam(Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        self.declare_parameter('my_parameter', 'world')

        self.timer = self.create_timer(1, self.timer_callback)

    def timer_callback(self):
        my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

        self.get_logger().info('Hello %s!' % my_param)

        my_new_param = rclpy.parameter.Parameter(
            'my_parameter',
            rclpy.Parameter.Type.STRING,
            'world'
        )
        all_new_parameters = [my_new_param]
        self.set_parameters(all_new_parameters)

def main():
    rclpy.init()
    node = MinimalParam()
    rclpy.spin(node)

if __name__ == '__main__':
    main()

a. Examine the code

The import statements at the top are used to import the package dependencies.

The next piece of code creates the class and the constructor. The line self.declare_parameter('my_parameter', 'world') of the constructor creates a parameter with the name my_parameter and a default value of world. The parameter type is inferred from the default value, so in this case, it would be set to a string type. Next, the timer is initialized with a period of 1, which causes the timer_callback function to be executed once a second.

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        self.declare_parameter('my_parameter', 'world')

        self.timer = self.create_timer(1, self.timer_callback)

The first line of our timer_callback function gets the parameter my_parameter from the node and stores it in my_param. Next, the get_logger function ensures the event is logged. The set_parameters function then sets the parameter my_parameter back to the default string value world. In the case that the user changed the parameter externally, this ensures it is always reset back to the original.

def timer_callback(self):
    my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

    self.get_logger().info('Hello %s!' % my_param)

    my_new_param = rclpy.parameter.Parameter(
        'my_parameter',
        rclpy.Parameter.Type.STRING,
        'world'
    )
    all_new_parameters = [my_new_param]
    self.set_parameters(all_new_parameters)

Following the timer_callback is our main. Here ROS 2 is initialized, an instance of the MinimalParam class is constructed, and rclpy.spin starts processing data from the node.

def main():
    rclpy.init()
    node = MinimalParam()
    rclpy.spin(node)

if __name__ == '__main__':
    main()

b. Add ParameterDescriptor (Optional)

Optionally, you can set a descriptor for the parameter. Descriptors allow you to specify a text description of the parameter and its constraints, like making it read-only, specifying a range, etc. For that to work, the __init__ code has to be changed to:

# ...

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        from rcl_interfaces.msg import ParameterDescriptor
        my_parameter_descriptor = ParameterDescriptor(description='This parameter is mine!')

        self.declare_parameter('my_parameter', 'world', my_parameter_descriptor)

        self.timer = self.create_timer(1, self.timer_callback)

The rest of the code remains the same. Once you run the node, you can then run ros2 param describe /minimal_param_node my_parameter to see the type and description.

2. Add an entry point

Reopen setup.py and add the entry point for the subscriber node below the publisher’s entry point. The entry_points field should now look like this: