What are ROS Parameters?
Parameters are globally available values such as integers, floats, strings or booleans. Any node in ROS can access and modify these values. You should use parameters for data that you do not expect to change a lot over time.
Nodes (i.e. programs in C++/Python that exist inside ROS packages), can use parameters during runtime.
Parameters are stored inside a centralized Parameter Server. The Parameter Server is like a dictionary that contains the name of the parameter and the corresponding value of the parameter.
The Parameter Server is part of the ROS Master, so it launches automatically when you launch either roscore or roslaunch.
You can learn more about the Parameter Server on the ROS website. There is also a quick tutorial on ROS parameters here if you’d like to dive deep.
Let’s look at some basic commands now.
Most Common Parameter Commands
To get a list of the currently active parameters on your system, open a new terminal window, and type:
roscore
rosparam list
Here we see the name of the active parameters.
If you want to see the value of the parameter, you use this syntax:
rosparam get <name_of_parameter>
For example, type:
rosparam get /rosdistro
We see that the value of the /rosdistro (i.e. “ROS distribution”) is noetic, which is exactly what we would expect.
If you want to see the values of all parameters at once, you type this command:
rosparam get /
To assign a value to a parameter, you use this command.
rosparam set <name_of_parameter> <desired_value>
Followed by this command to complete the update of the parameter value.
rosservice call /clear
How to Update Parameters Using the dynamic_reconfigure Package
Imagine we have two nodes written in either Python or C++. One node sets the value of a particular parameter on the Parameter Server. The other node uses the value of that parameter to perform some computation. This latter node typically reads the value of the parameter only when the node is first launched. How will this latter node know if the value of the parameter has changed during runtime?
Fortunately, ROS has an efficient solution for this. To update the value of a parameter dynamically (i.e. “on-the-fly”) while a node is running, we can use the dynamic_reconfigure package. This package enables us to update parameters on the Parameter Server at runtime and push that change out to a given active node that needs the most current value of that parameter.
This is cool because it means we don’t have to restart a node in order for it to recognize the change in the value of a parameter.
A common use case for the dynamic_reconfigure package is when you’ve built a control system that needs to precisely control the speed of a motor. You might need to continuously tune the control parameters to make the robot move how you want it to move. Doing so requires continuous updates. The dynamic_reconfigure package provides an efficient means of doing this.
Let’s take a look at an example of how to use the dynamic_reconfigure package. The official ROS tutorial for this package is here (for both C++ and Python). We’ll run through the process below for C++.
How to Write a .cfg File
First, let’s create a package called parameter_server_basics.
In a new terminal window, move to the src (source) folder of your workspace.
cd ~/catkin_ws/src
Now create the package (everything below goes on one line in the terminal)
catkin_create_pkg parameter_server_basics std_msgs roscpp rospy dynamic_reconfigure
Now, let’s build the package.
cd ~/catkin_ws/
catkin_make
Now, move inside the package.
roscd parameter_server_basics
Create a cfg directory. This is where all the cfg files will be.
mkdir cfg
Move inside the cfg directory you just created.
cd cfg
Now let’s create a file named parameter_server_basics.cfg.
gedit parameter_server_basics.cfg
Write the following code:
#!/usr/bin/env python3
PACKAGE = "parameter_server_basics"
from dynamic_reconfigure.parameter_generator_catkin import *
gen = ParameterGenerator()
gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100)
gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1)
gen.add("str_param", str_t, 0, "A string parameter", "Hello World")
gen.add("bool_param", bool_t, 0, "A Boolean parameter", True)
size_enum = gen.enum([ gen.const("Small", int_t, 0, "A small constant"),
gen.const("Medium", int_t, 1, "A medium constant"),
gen.const("Large", int_t, 2, "A large constant"),
gen.const("ExtraLarge", int_t, 3, "An extra large constant")],
"An enum to set size")
gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum)
exit(gen.generate(PACKAGE, "parameter_server_basics", "parameter_server_"))
To understand what the code is all about, check out this post.
Save the file and close the editor.
Make the code executable:
chmod +x parameter_server_basics.cfg
Now go back to the directory of the package.
roscd parameter_server_basics
Open the CMakeLists.txt file.
gedit CMakeLists.txt
Add these lines to the lines just underneath the “find_package()” block:
#add dynamic reconfigure api
#find_package(catkin REQUIRED dynamic_reconfigure)
generate_dynamic_reconfigure_options(
cfg/parameter_server_basics.cfg
#...
)
Add these lines to the very bottom of the file.
# make sure configure headers are built before any node using them
add_dependencies(parameter_server_basics ${PROJECT_NAME}_gencfg)
Click Save and close the editor window.
How to Make a Node Dynamically Reconfigureable in C++
Now we need to create a node that uses the cfg file. We will create a node in C++, but you can also create a node using Python.
Go to your parameter_server_basics package.
roscd parameter_server_basics
Go inside the src folder.
cd src
Open a new C++ file named
parameter_server_basics.cpp
Add the code below into the file. For a detailed explanation of what is going on inside the code, check out this post.
#include <ros/ros.h>
#include <dynamic_reconfigure/server.h>
#include <parameter_server_basics/parameter_server_Config.h>
void callback(parameter_server_basics::parameter_server_Config &config, uint32_t level) {
ROS_INFO("Reconfigure Request: %d %f %s %s %d",
config.int_param, config.double_param,
config.str_param.c_str(),
config.bool_param?"True":"False",
config.size);
}
int main(int argc, char **argv) {
ros::init(argc, argv, "parameter_server_basics");
dynamic_reconfigure::Server<parameter_server_basics::parameter_server_Config> server;
dynamic_reconfigure::Server<parameter_server_basics::parameter_server_Config>::CallbackType f;
f = boost::bind(&callback, _1, _2);
server.setCallback(f);
ROS_INFO("Spinning node");
ros::spin();
return 0;
}
Let’s edit the CMakeLists.txt file for the parameter_server_basics package.
Open a new terminal window, and type this command:
roscd parameter_server_basics
gedit CMakeLists.txt
Now add these lines to the bottom of the CMakeLists.txt file. Make sure the add_dependencies line you added in the last section is between add_executable… and target_link_libraries:
add_executable(parameter_server_basics src/parameter_server_basics.cpp)
target_link_libraries(parameter_server_basics ${catkin_LIBRARIES})
Now save and close the CMakeLists.txt file.
Open a new terminal window, and type the following commands to build all the nodes in the parameter_server_basics package:
cd ~/catkin_ws
catkin_make
If everything goes, well, here is the message you should see:
We need to modify the rqt_reconfigure node so that it runs with Python 3.
Open up a new terminal window, and type:
sudo ln -s /usr/bin/python3 /usr/bin/python
This will make a symbolic link from /usr/local/bin/python to /usr/bin/python3.
Now that everything is setup, let’s run the node and the Dynamic Reconfigure Graphical User Interface.
Open a new terminal window to launch ROS.
roscore
In a new terminal tab, type:
rosrun parameter_server_basics parameter_server_basics
In another terminal tab, type:
rosrun rqt_reconfigure rqt_reconfigure
Click on parameter_server_basics on the left-hand side.
Here is what you should see:
To modify the parameters, drag any of the sliders. You can also uncheck the boolean checkbox there.
Each time you make a change to one of the parameters, you’ll see the change printed out to the terminal window where you ran rosrun parameter_server_basics parameter_server_basics.
When you’re finished, type Ctrl + C on all terminal windows to shutdown ROS.