Writing configuration files
From The Player Project
Player needs to know which drivers to instantiate and to which device addresses each should be bound. This information is usually specified in a Player configuration file (it can also be done directly from code by calling into libplayercore).
A Player configuration file is a text file that, by convention, has the extension .cfg. The file is composed of one or more driver sections, each of which instantiates and configures a single driver. Consider an example:
driver ( name "sicklms200" provides ["laser:0"] )
This block instantiates the sicklms200 driver. The provides keyword is used to specify the device address to which the driver will be bound. Using this configuration, an instance of the sicklms200 driver will be available as laser :0.
A driver section is declared by the keyword driver( ). Option-value pairs for the driver go inside the parentheses. An option and its value are whitespace-separated, as are consecutive option-value pairs. All standard whitespace characters are treated equally, so that the following section is equivalent to the one given above:
driver (name "sicklms200" provides ["laser:0"])
Comments are signified by the #character. Any characters following the # up to the next newline are ignored. E.g.:
# A laser driver ( name "sicklms200" # The driver's name provides ["laser:0"] # The device address )
There are four driver-independent options:
- name (string) : The name of the driver to instantiate, as it was provided to DriverTable::AddDriver(). This option is mandatory.
- plugin (string) : The name of a shared library (i.e., a "plugin") that contains the driver. This shared library will be loaded before attempting to instantiate the driver. See Writing a Player driver for more information on writing and using driver plugins.
- provides (tuple of strings): The device address(es) through which the driver can be accessed. This option is mandatory.
- requires (tuple of strings): The device address(es) to which the driver will subscribe.
Most drivers (e.g., sicklms200) support a single interface. Thus their provides value is a tuple containing a single string.
provides ["localize:0" "position2d:0"]
For most (though not all) multi-interface drivers, you can request just the subset of the supported interfaces that you need. So in the amcl example above, you could leave out either "localize:0" or "position2d:0", as the situation warrants. Every driver must provide at least one device (otherwise there's no way to access it).
Most drivers (e.g., sicklms200) don't need any other devices to do their work. Thus no requires option is given.
Some drivers require other devices. For example, the vfh driver, a local navigation / obstacle-avoidance algorithm, needs two devices: a position2d device to command and a laser device from which to read laser scans. This driver in turn provides a position2d device to which target poses can be sent. So the vfh driver might be configured like so:
driver ( name "vfh" provides ["position2d:1"] requires ["position2d:0" "laser:0"] )
Drivers providing "position2d:0" and "laser:0" must have already been declared. In general, a driver's required devices must be instantiated prior to the driver itself being instantiated. Circular dependencies are not allowed.
Device addresses for the provides and requires options are given as strings in a 5-part colon-separated format:
Only the interface and index fields are required. Default values will be taken for any fields left blank. The default values for host and robot can vary depending on the context, but are usually "localhost" and 6665, respectively. The default value for the key field is NULL (i.e., no key). Leading fields can be omitted, but intermediate fields must be explicitly left blank. For example, to specify a key but leave host and robot blank:
The key field in a device address
The purpose of the key field is to allow a driver that supports multiple interfaces of the same type to map those interfaces onto different devices. For example, consider the p2os driver, which supports three position2d interfaces:
driver ( name "p2os" provides ["odometry:::position2d:0" "compass:::position2d:1" "gyro:::position2d:2"] )
This declaration says, provide the robot's odometry as position2d:0, the compass as position2d:1, and the gyro as position2d:2. The mapping of a driver's interfaces to devices is up to you. For example, instead of the example above, you could do this:
driver ( name "p2os" provides ["odometry:::position2d:14" "compass:::position2d:0" "gyro:::position2d:25"] )
That is, provide the robot's odometry as position2d:14, the compass as position2d:0, and the gyro as position2d:25.
The same goes for devices that are required by a driver. For example, the amcl driver can take as input different kinds of position2d devices and it treats them each differently; e.g., a different action model would be used for odometry data vs. IMU data. Likewise, the amcl driver can take as input different kinds of map devices; e.g., a laser-based map vs. a wifi signal-strength map. (Ignore for the moment that the features I've just mentioned aren't currently implemented in amcl). Consider:
driver ( name "amcl" provides ["localize:0"] requires ["odometry:::position2d:0" "laser:0" "laser:::map:0"] )
That is, take input from position2d:0 and treat it as odometry, and take input from map:0 and treat is a laser map. No key necessary for laser:0, because amcl only supports one laser interface.
The following types are supported for option values:
- integer : typed literally
- floating point : typed literally
- string : enclosed in double quotes
bat "hello world"
- length : typed literally (see discussion of Units below)
- angle : typed literally (see discussion of Units below)
- tuple : enclosed in brackets (types can be mixed)
widget [42 3.14159 "hello world" 8.0 180.0]
In order to aid the use of standard units, explicit types are provided for lengths and angles. When a driver reads a length from the configuration file, the value is always returned in meters. When an angle is read, the value is always returned in radians.
For convenience, the user may specify lengths and angles in the configuration using different units. By default, lengths are assumed to be given in meters, with angles in degrees. The units can be changed using the global (i.e., not inside a driver section) options unit_length and unit_angle; e.g.:
* unit_length "cm" # Change length units to centimeters * unit_angle "radians" # Change angle units to radians
Valid values for unit_length are:
* "m" : meters (default) * "cm" : centimeters * "mm" : millimeters
Valid values for unit_angle are:
* "degrees" : degrees (default) * "radians" : radians
These options are order-sensitive and sticky. A length (angle) is parsed in the context of the most recently-parsed unit_length (unit_angle) option. So you can change units multiple times as is convenient throughout the file.
Note that unit context extends into included files, so special care is needed when mixing units with file inclusion.
Including other files
Another file may be included via the global (i.e., not inside a driver section) include option:
The contents of the included file are parsed as if they had appeared literally, in place of the include statement. Any number of files may be included, and file inclusion may be nested.
Take care if mixing file inclusion with unit changes. Reserved words The following keywords are reserved and may not be used for option names:
The Player source code has a bunch of examples under the config/ directory