Contents
Basic Setup
To begin lets create a package called dynamic_tutorials which depends on rospy, roscpp and dynamic_reconfigure.
catkin_create_pkg --rosdistro ROSDISTRO dynamic_tutorials rospy roscpp dynamic_reconfigure
Where ROSDISTRO is the ROS distribution you are using.
Now in your package create a cfg directory, this is where all cfg files live:
mkdir cfg
Lastly you will need to create a cfg file, for this example we'll call it Tutorials.cfg, and open it in your favorite editor.
The cfg File
Add the following to your Tutorials.cfg file:
1 #!/usr/bin/env python
2 PACKAGE = "dynamic_tutorials"
3
4 from dynamic_reconfigure.parameter_generator_catkin import *
5
6 gen = ParameterGenerator()
7
8 gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100)
9 gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1)
10 gen.add("str_param", str_t, 0, "A string parameter", "Hello World")
11 gen.add("bool_param", bool_t, 0, "A Boolean parameter", True)
12
13 size_enum = gen.enum([ gen.const("Small", int_t, 0, "A small constant"),
14 gen.const("Medium", int_t, 1, "A medium constant"),
15 gen.const("Large", int_t, 2, "A large constant"),
16 gen.const("ExtraLarge", int_t, 3, "An extra large constant")],
17 "An enum to set size")
18
19 gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum)
20
21 exit(gen.generate(PACKAGE, "dynamic_tutorials", "Tutorials"))
Now lets break the code down line by line.
This first lines are pretty simple, they just initialize ros and import the parameter generator.
6 gen = ParameterGenerator()
Now that we have a generator we can start to define parameters. The add function adds a parameter to the list of parameters. It takes a few different arguments:
name - a string which specifies the name under which this parameter should be stored
paramtype - defines the type of value stored, and can be any of int_t, double_t, str_t, or bool_t
level - A bitmask which will later be passed to the dynamic reconfigure callback. When the callback is called all of the level values for parameters that have been changed are ORed together and the resulting value is passed to the callback.
description - string which describes the parameter
default - specifies the default value
min - specifies the min value (optional and does not apply to strings and bools)
max - specifies the max value (optional and does not apply to strings and bools)
These lines simply define more parameters of the different types.
13 size_enum = gen.enum([ gen.const("Small", int_t, 0, "A small constant"),
14 gen.const("Medium", int_t, 1, "A medium constant"),
15 gen.const("Large", int_t, 2, "A large constant"),
16 gen.const("ExtraLarge", int_t, 3, "An extra large constant")],
17 "An enum to set size")
18
19 gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum)
Here we define an integer whose value is set by an enum. To do this we call gen.enum and pass it a list of constants followed by a description of the enum. Now that we have created an enum we can now pass it to the generator. Now the param can be set with "Small" or "Medium" rather than 0 or 1.
21 exit(gen.generate(PACKAGE, "dynamic_tutorials", "Tutorials"))
The last line simply tells the generator to generate the necessary files and exit the program. The second parameter is the name of a node this could run in (used to generate documentation only), the third parameter is a name prefix the generated files will get (e.g. "<name>Config.h" for c++, or "<name>Config.py" for python.
NOTE: The third parameter should be equal to the cfg file name, without extension. Otherwise the libraries will be generated in every build, forcing a recompilation of the nodes which use them.
Use the cfg File
In order to make this cfg file usable it must be executable, so lets use the following command to make it excecutable
chmod a+x cfg/Tutorials.cfg
Next we need to add the following lines to our CMakeLists.txt. For Groovy and above
#add dynamic reconfigure api #find_package(catkin REQUIRED dynamic_reconfigure) generate_dynamic_reconfigure_options( cfg/Tutorials.cfg #... ) # make sure configure headers are built before any node using them add_dependencies(example_node ${PROJECT_NAME}_gencfg)
Note that you need a node example_node that is already built, before the add_dependencies line is reached (ref Create a node in C++).
This will run our cfg when the package is built. The last thing to do is to build the package and we're done!