(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

How to Write Your First .cfg File

Description: This tutorial will familiarize you with .cfg files that allow you to use dynamic_reconfigure.

Tutorial Level: INTERMEDIATE

Next Tutorial: Setting up Dynamic Reconfigure for a Node(c++) Setting up Dynamic Reconfigure for a Node(python)

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.

   1 #!/usr/bin/env python
   2 PACKAGE = "dynamic_tutorials"
   3 
   4 from dynamic_reconfigure.parameter_generator_catkin import *

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)

   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)

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!

Basic Setup

To begin lets create a package called dynamic_tutorials which depedns on rospy roscpp and dynamic_reconfigure like so:

roscreate-pkg dynamic_tutorials rospy roscpp dynamic_reconfigure

Now in your package create a cfg directory, this is where all cfg files live. 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 cfg file:

   1 #!/usr/bin/env python
   2 PACKAGE = "dynamic_tutorials"
   3 
   4 import roslib;roslib.load_manifest(PACKAGE)
   5 
   6 from dynamic_reconfigure.parameter_generator import *
   7 
   8 gen = ParameterGenerator()
   9 
  10 gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100)
  11 gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1)
  12 gen.add("str_param", str_t, 0, "A string parameter", "Hello World")
  13 gen.add("bool_param", bool_t, 0, "A Boolean parameter", True)
  14 
  15 size_enum = gen.enum([ gen.const("Small", int_t, 0, "A small constant"),
  16                   gen.const("Medium", int_t, 1, "A medium constant"),
  17                   gen.const("Large", int_t, 2, "A large constant"),
  18                   gen.const("ExtraLarge", int_t, 3, "An extra large constant") ],
  19                   "An enum to set size")
  20 
  21 gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum)
  22 
  23 exit(gen.generate(PACKAGE, "dynamic_tutorials", "Tutorials"))

Now lets break the code down line by line.

   1 #!/usr/bin/env python
   2 PACKAGE = "dynamic_tutorials"
   3 
   4 import roslib;roslib.load_manifest(PACKAGE)
   5 
   6 from dynamic_reconfigure.parameter_generator import *

This first lines are pretty simple, they just initialize ros and import the parameter generator.

   8 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

  • type - 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)

  10 gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100)
  11 gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1)
  12 gen.add("str_param", str_t, 0, "A string parameter", "Hello World")
  13 gen.add("bool_param", bool_t, 0, "A Boolean parameter", True)

These lines simply define more parameters of the different types.

  14 size_enum = gen.enum([ gen.const("Small", int_t, 0, "A small constant"),
  15                   gen.const("Medium", int_t, 1, "A medium constant"),
  16                   gen.const("Large", int_t, 2, "A large constant"),
  17                   gen.const("ExtraLarge", int_t, 3, "An extra large constant") ],
  18                   "An enum to set size")
  19 
  20 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.

  23 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.

#add dynamic reconfigure api
rosbuild_find_ros_package(dynamic_reconfigure)
include(${dynamic_reconfigure_PACKAGE_PATH}/cmake/cfgbuild.cmake)
gencfg()

This will run our cfg when the package is built. The last thing to do is to build the package and we're done!

Wiki: dynamic_reconfigure/Tutorials/HowToWriteYourFirstCfgFile (last edited 2014-10-31 15:52:29 by ProcopioStein)