YARP  2.3.70.1
Yet Another Robot Platform
YARP config files
Author
Paul Fitzpatrick

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

A minimal config file

Here is a minimal config file, let's call it "config.ini" (the extension doesn't matter):

width 10
height 15

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

Accessing the minimal config file from code

We could read the example config file in the above section, by doing the following in code:

int main() {
prop.fromConfigFile("config.ini");
// ... query prop object here ...
return 0;
}

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:

prop.findGroup("width") // gives the list [width,10]
prop.findGroup("height") // gives the list [height,15]

In general, the list of values associated with a group can be found with the tail command, which drops the keyword:

prop.findGroup("width").tail() // gives the list [10]

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.

prop.find("width").asInt() // gives the int 10
prop.find("height").asInt() // gives the int 15

A config file with sections

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:

[SIZE]
width 10
height 15
[APPEARANCE]
color red

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:

prop.findGroup("SIZE").find("width").asInt() // gives 10
prop.findGroup("APPEARANCE").find("color").asString() // gives "red"

In fact, in YARP config files, the above structure could also be written as:

SIZE (width 10) (height 15)
APPEARANCE (color red)

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.

Nesting configuration files

To include one configuration file, say "preamble.ini", inside another one, do:

[include "preamble.ini"]

This will insert the content of preamble.ini as if cut-and-pasted. If you would rather have the content included within a subsection called FOO, do instead:

[include FOO "preamble.ini"]

This last form will result in any sections within preamble.ini being nested within FOO.

For example, if preamble.ini is:

alpha 0.5
[tweaks]
pnudge 10 -10

Then with a config.ini of:

x 10
y 10
[include "preamble.ini"]

we end up with top-level groups of x, y, alpha, and tweaks. With a config.ini of:

x 10
y 10
[include setup "preamble.ini"]

we end up with top-level groups of x, y, and setup (alpha and tweaks are nested within setup).

As of YARP 2.3.21, it is 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.

Section collections

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:

[camera left]
geom 0.7 0.3
color_correct 0.01 0.0 -0.1
[camera right]
geom -0.7 0.3
color_correct 0.0 0.0 0.0

This configuration file is equivalent to:

camera left right
[left]
geom 0.7 0.3
color_correct 0.01 0.0 -0.1
[right]
geom -0.7 0.3
color_correct 0.0 0.0 0.0

So we have a handy "camera" list accessible as prop.findGroup("camera").tail() that gives us the names of the camera-related groups.

Combining section collections and includes

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:

[include camera left "cam_left.ini"]
[include camera right "cam_right.ini"]

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:

camera left right

Combining section collections and directory includes

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:

[camera left]
geom 0.7 0.3
color_correct 0.01 0.0 -0.1

And a file cam/right.ini containing:

[camera right]
geom -0.7 0.3
color_correct 0.0 0.0 0.0

And a file all.ini containing:

[include "cam"]

Loading all.ini is equivalent to loading:

camera left right
[left]
geom 0.7 0.3
color_correct 0.01 0.0 -0.1
[right]
geom -0.7 0.3
color_correct 0.0 0.0 0.0

Note the ordering of files read may not be defined.

Comments in config files

Use the # character, or //, as your prefer.

# this is a comment
// this is also a comment

Quoting in config files

Keys, values, and section names containing spaces or special characters should be surrounded by double-quotes, for example:

"a long key whose string value looks like a list" "(1 2 3)"

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.

Continuing across lines

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:

encoders (1 2 3 4 \
5 6 7 8)

is the same as:

encoders (1 2 3 4 5 6 7 8)

List syntax

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:

example_list (1 2 3)
nested_list (foo (red (255 0 0)) (green (0 255 0)))

Binary blobs are also supported, and are expressed as lists of space-separated numbers surrounded by square parentheses.

Expansion of variables

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:

username "$USER"
tmpdir "/tmp/robot_${username}_cache"

This would give "tmpdir" set to "/tmp/robot_paulfitz_cache".

Extra "psuedo-environment" variables can be made available by calling yarp::os::Property::fromConfigFile with an extra Property argument.

Compatibility with other INI readers

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:

x 10
x = 10

Don't forget the spaces, and don't do anything fancy beyond key/value pairs.

Command line configuration switches

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:

int main(int argc, char *argv[]) {
ResourceFinder prop;
prop.configure(argc,argv);
...
}

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:

width 10
height 15

And the program is called with these arguments:

--from config.ini --width 200

In this case, we get:

prop.find("width").asInt() // gives the int 200
prop.find("height").asInt() // gives the int 15

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:

[SIZE]
width 10
height 15
[APPEARANCE]
color red

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