/** @ingroup tutorials @defgroup tutorial_config Writing configuration files @brief Config files Table of contents: - @ref overview - @ref syntax - @ref driver_options - @ref provides - @ref requires - @ref device_addresses - @ref device_key - @ref types - @ref units - @ref includes - @ref keywords - @ref examples @section overview Overview 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 @ref 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: @code driver ( name "sicklms200" provides ["laser:0"] ) @endcode This block instantiates the @ref driver_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 @ref driver_sicklms200 driver will be available as @ref interface_laser :0. @section syntax Basic syntax 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: @code driver (name "sicklms200" provides ["laser:0"]) @endcode Comments are signified by the #character. Any characters following the # up to the next newline are ignored. E.g.: @code # A laser driver ( name "sicklms200" # The driver's name provides ["laser:0"] # The device address ) @endcode @section driver_options Driver-independent options There are four driver-independent options: - @b name (string) : The name of the driver to instantiate, as it was provided to DriverTable::AddDriver(). This option is mandatory. - @b 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 @ref tutorial_plugins for more information on writing and using driver plugins. - @b provides (tuple of strings): The device address(es) through which the driver can be accessed. This option is mandatory. - @b requires (tuple of strings): The device address(es) to which the driver will subscribe. @subsection provides provides Most drivers (e.g., @ref driver_sicklms200) support a single interface. Thus their @b provides value is a tuple containing a single string. Some drivers support multiple interfaces. For example, the @ref driver_amcl driver supports the @ref interface_localize and the @ref interface_position2d interfaces, so its @b provides line might look like this: @code provides ["localize:0" "position2d:0"] @endcode For most (though not all) multi-interface drivers, you can request just the subset of the supported interfaces that you need. So in the @ref driver_amcl example above, you could leave out either @b "localize:0" or @b "position2d:0", as the situation warrants. Every driver must provide at least one device (otherwise there's no way to access it). @subsection requires requires Most drivers (e.g., @ref driver_sicklms200) don't need any other devices to do their work. Thus no @b requires option is given. Some drivers require other devices. For example, the @ref driver_vfh driver, a local navigation / obstacle-avoidance algorithm, needs two devices: a @ref interface_position2d device to command and a @ref interface_laser device from which to read laser scans. This driver in turn provides a @ref interface_position2d device to which target poses can be sent. So the @ref driver_vfh driver might be configured like so: @code driver ( name "vfh" provides ["position2d:1"] requires ["position2d:0" "laser:0"] ) @endcode Drivers providing @b "position2d:0" and @b "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. @subsection device_addresses Device addresses %Device addresses for the @b provides and @b requires options are given as strings in a 5-part colon-separated format: @code key:host:robot:interface:index @endcode Only the @b interface and @b index fields are required. Default values will be taken for any fields left blank. The default values for @b host and @b robot can vary depending on the context, but are usually @b "localhost" and @b 6665, respectively. The default value for the @b 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 @b key but leave @b host and @b robot blank: @code odometry:::position2d:0 @endcode @subsection device_key The key field in a device address The purpose of the @b 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 @ref driver_p2os driver, which supports three @ref interface_position2d interfaces: @code driver ( name "p2os" provides ["odometry:::position2d:0" "compass:::position2d:1" "gyro:::position2d:2"] ) @endcode This declaration says, provide the robot's odometry as @b position2d:0, the compass as @b position2d:1, and the gyro as @b 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: @code driver ( name "p2os" provides ["odometry:::position2d:14" "compass:::position2d:0" "gyro:::position2d:25"] ) @endcode That is, provide the robot's odometry as @b position2d:14, the compass as @b position2d:0, and the gyro as @b position2d:25. The same goes for devices that are required by a driver. For example, the @ref driver_amcl driver can take as input different kinds of @ref interface_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 @ref driver_amcl driver can take as input different kinds of @ref interface_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: @code driver ( name "amcl" provides ["localize:0"] requires ["odometry:::position2d:0" "laser:0" "laser:::map:0"] ) @endcode That is, take input from @b position2d:0 and treat it as odometry, and take input from @b map:0 and treat is a laser map. No key necessary for @b laser:0, because @ref driver_amcl only supports one @ref interface_laser interface. @section types Types The following types are supported for option values: - integer : typed literally - Example: @code foo 42 @endcode - floating point : typed literally - Example: @code bar 3.14159 @endcode - string : enclosed in double quotes - Example: @code bat "hello world" @endcode - length : typed literally (see discussion of Units below) - Example: @code baz 8.0 @endcode - angle : typed literally (see discussion of Units below) - Example: @code bang 180.0 @endcode - tuple : enclosed in brackets (types can be mixed) - Example: @code widget [42 3.14159 "hello world" 8.0 180.0] @endcode @section units Units 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.: @code unit_length "cm" # Change length units to centimeters unit_angle "radians" # Change angle units to radians @endcode 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. @section includes Including other files Another file may be included via the global (i.e., not inside a @b driver section) @b include option: @code include "another_file.cfg" @endcode The contents of the included file are parsed as if they had appeared literally, in place of the @b include statement. Any number of files may be included, and file inclusion may be nested. Take care if mixing file inclusion with unit changes. @section keywords Reserved words The following keywords are reserved and may not be used for option names: - @b driver - @b name - @b plugin - @b provides - @b requires - @b unit_length - @b unit_angle @section examples Examples @todo Put some useful examples here */