This tutorial covers how to write and read configuration files in YARP's native format.
In brief, YARP config files look a lot like INI files but are actually closer in spirit to S-expressions. YARP config files translate into yarp::os::Property
objects (see e.g. the yarp::os::Property::fromConfigFile
command).
Here is a minimal config file, let's call it "config.ini" (the extension doesn't matter):
The format of each line is the same as that of the string representation of the yarp::os::Bottle class, defined here: Standard data representation format. In summary, each line is a list of items (strings, numbers, sublists, etc) separated by spaces/tabs. We call each top-level list a "group", and assign a name to each group based on its first element.
This "config.ini" example contains two groups, one called "width", and the other called "height".
We could read the example config file in the above section, by doing the following in code:
The Property object prop will contain all the groups in the configuration file. The groups can be accessed by iterating, or by using the yarp::os::Property::findGroup command. This takes a keyword as an argument, and returns the group that has that keyword as its first element. So for config.ini:
In general, the list of values associated with a group can be found with the tail command, which drops the keyword:
Since it is common to use groups of two elements to represent simple key-value pairs, there is a shorthand command yarp::os::Property::find to get the second element of a group directly. It returns a yarp::os::Value object which can easily be converted to regular C types.
Configuration files often need to have nesting, with values organized into sections. Special tags of the form "[NAME]" are one way to achieve this with YARP config files (or INI-style configuration files in general). For example, for a file containing:
the Property object we read in code will now contain the two groups "SIZE" and "APPEARANCE", which will have "width", "height", and "color" nested within them. In other words:
In fact, in YARP config files, the above structure could also be written as:
This is exactly equivalent. The special [SECTION] syntax is just a convenience, familiar to many from INI files.
Here is the rule. Any list on a separate line in a configuration file, with any degree of nesting, is a group. That means it can be found using the findGroup/find commands, with its name being given by its first element. Any sublists within that group can be found recursively in code using findGroup/find, again with their names being given by their first element.
What happens if there are multiple groups at the same level with the same name? That is undefined, and whatever YARP's current behavior is for this case is not guaranteed to remain so in the future.
To include one configuration file, say "preamble.ini", inside another one, do:
This will insert the content of preamble.ini as if cut-and-pasted. If the .ini file is not located in the current directory you have to specify the path to reach it.
If you would rather have the content included within a subsection called FOO, do instead:
This last form will result in any sections within preamble.ini being nested within FOO.
For example, if preamble.ini is:
Then with a config.ini of:
we end up with top-level groups of x, y, alpha, and tweaks. With a config.ini of:
we end up with top-level groups of x, y, and setup (alpha and tweaks are nested within setup).
It is also possible to include a whole directory. In this case, all files with the extension ".ini" from that directory will be merged together. An example is given in Combining section collections and directory includes.
If you need to include a configuration file from a specific context, using yarp::os::ResourceFinder (ResourceFinder Tutorials and Specification) do:
The import tag also supports multi-level nesting. The imported file is inserted at the specific point where the import directive is found, as if cut-and-pasted. It is not possibile to import a file inside a section, as done using the syntax [include FOO filename.ini] previously described. The options included by the imported file may be overwritten by the options located in the parent configuration file (or viceversa), so be careful about the order in which the parameters are processed. This mechanism can be exploited to include a base configuration file and then override specific parameters.
Occasionally a config file needs a list of sections containing similar entries. One convenient way to achieve that is with a "section prefix". For example:
This configuration file is equivalent to:
So we have a handy "camera" list accessible as prop.findGroup("camera").tail() that gives us the names of the camera-related groups.
As of YARP 2.2.8, section collections and include file features can be combined. In other words, one can have a configuration file like this:
This takes the material in "cam_left.ini" and places it in a section called "left", and similarly places the material in "cam_right.ini" in a section called "right", and then creates a group called "camera" equivalent to the following line:
As of YARP 2.3.21, it is possible to include a whole directory in place of a file. That gives new possibilities for section collections. Suppose we have a file cam/left.ini containing:
And a file cam/right.ini containing:
And a file all.ini containing:
Loading all.ini is equivalent to loading:
Note the ordering of files read may not be defined.
Use the # character, or //, as your prefer.
Keys, values, and section names containing spaces or special characters should be surrounded by double-quotes, for example:
maps the string "a long key whose string value looks like a list" to the string "(1 2 3)".
If the quote character needs to be included in a string it can be itself quoted by preceding it with a backslash character.
A long line can be continued on the next line by breaking the line up with a backslash character directly before the end of line. For example:
is the same as:
Values in a config file can be any type supported by yarp::os::Bottle. That includes lists, which are surrounded by parentheses and have spaces (not commas) between items:
Binary blobs are also supported, and are expressed as lists of space-separated numbers surrounded by square parentheses.
By default, environment variables in the config file written as $NAME or ${NAME} will be expanded. To include a dollar sign without expansion, precede it with a backslash.
Key/value pairs already encountered in the config file can also be used in this way. For example, in an environment where USER is set to paulfitz:
This would give "tmpdir" set to "/tmp/robot_paulfitz_cache".
Extra "pseudo-environment" variables can be made available by calling yarp::os::Property::fromConfigFile with an extra Property argument.
Occasionally it is nice to be able to read YARP config files from other systems (e.g. Python has an INI reader). Your best bet to do that is to include an equals sign between keys and values, with spaces around the equals. YARP will accept and ignore this, and it will make other readers happier. For YARP, these two lines are equivalent:
Don't forget the spaces, and don't do anything fancy beyond key/value pairs.
The yarp::os::ResourceFinder class bundles together some common ways to configure YARP programs. An instance of this class is usually passed the command line arguments:
The yarp::os::ResourceFinder class can be used just like the yarp::os::Property class mentioned in: Accessing the minimal config file from code. If the user of the program supplies a –from config.ini
argument that file shall be read as a configuration file. Values can be overridden on the command line. For example, if config.ini
contains:
And the program is called with these arguments:
--from config.ini --width 200
In this case, we get:
This can be handy to override one or two values in a long config file without needing to copy it and modify it. One wrinkle remains – how to override values that are in sections? For example, if config.ini
is:
Then calling the program with –width 200
would simply add a new top-level width
value without modifying the width
in the SIZE
section. As of yarp 2.3.20, it is possible to use a nested notation in the command line, and call the program as:
--from config.ini --SIZE::width 200