New Experiment Definition File Plugin (--expdef)#

This page covers the contract that experiment definition template files must satisfy, independent of format, and then walks through how to create a new Plugin for a custom file format. See Experiment Templates for a user-facing introduction, and Plugin Development Guide for the general plugin development guide.

Template File Contract#

An experiment definition template is a single file passed to --expdef-template. SIERRA reads it once per batch and applies modifications from batch criteria and controllers.yaml to produce per-experiment, per-run input files. Two requirements apply regardless of format:

  1. Single file. The template must be a single file. Any configuration not reachable within it cannot be varied by SIERRA.

    If your simulator normally expects multiple configuration files (a common pattern in, e.g., ROS launch setups), you have two options:

    1. Flatten the configuration into a single file. Each expdef plugin may implement a flatten(keys) method (see New Experiment Definition File Plugin (--expdef)) that inlines external-file references identified by keys. An Engine plugin invokes this at the start of stage 1, backend-agnostically, by resolving the expdef module from --expdef and calling flatten() on it. Not every backend implements flattening (e.g., the XML plugin does not). See New Engine Plugin (--engine) for how the engine drives this.

    2. Factor out only the parameters SIERRA needs to vary into the template and load the remaining files from fixed paths within your project. This is the pragmatic approach for large legacy configurations where flattening is not practical.

  2. Unique node paths. Every element and attribute SIERRA needs to target must be uniquely identifiable by a path from the root of the file. For XML this is XPath; for JSON, JSONPath; for YAML, YAMLPath. If your file format has no companion query language you will need to write one.

Special Tokens#

SIERRA recognises the following tokens during stage 1 and substitutes them before writing per-run input files. They must appear in the locations described — SIERRA only looks for them in specific places.

__CONTROLLER__

A placeholder for the controller name in the template file. SIERRA replaces it with the controller name derived from --controller and controllers.yaml. Supported in XML, JSON, and YAML templates.

In XML templates, __CONTROLLER__ appears as an element tag name:

<__CONTROLLER__ library="...">
  ...
</__CONTROLLER__>

In JSON and YAML templates, it appears as a key whose value SIERRA overwrites with the resolved controller name:

{ "__CONTROLLER__" : "..." }
__CONTROLLER__: "..."

For how to target __CONTROLLER__ from controllers.yaml, see Special Tokens in controllers.yaml.

__UUID__

Available in ROS1 .launch templates when a ROS1 engine is selected. Expands to the robot's namespace prefix concatenated with its numeric ID (0-based); the enclosing tag is added once per robot rather than once overall. Used to set per-robot parameters that cannot be controlled through batch criteria. For usage in controllers.yaml, see Special Tokens in controllers.yaml.

sierra (namespace)

Reserved. Must not appear as an XML tag name or attribute value in ROS1 .launch templates. SIERRA uses this namespace internally.

Format-Specific Restrictions#

XML

Modifications use XPath expressions (Python xml.etree.ElementTree syntax) to locate elements and attributes. The full XPath subset supported is documented in the Python standard library.

JSON and YAML

SIERRA distinguishes between keys that map to scalar values and keys that map to nested objects. Batch criteria and controllers.yaml can only target scalar-valued keys. Attempting to modify a key that maps to a subtree raises an error, even though such a modification would be valid JSON or YAML. This restriction exists to keep modification semantics uniform across all supported formats.

ROS1 launch files

A dialect of XML. Subject to the XML restrictions above, plus the sierra namespace reservation and __UUID__ token described under Special Tokens.

Creating a New Expdef Plugin#

For the purposes of this tutorial, I will assume you are creating a new Plugin fizzbuzz for reading in and creating experiment definitions from an imaginary "fizzbuzz" file type. Before beginning, see Plugin Development Guide for a general overview of creating a new plugin.

To begin, create the following filesystem structure in $HOME/git/plugins/fizzbuzz.

  • plugin.py - This file is required, and is where most of the bits for the plugin will go. You don't have to call it this; if you want to use a different name, see Schemas for options.

  • cmdline.py This file is optional. If your new plugin doesn't need any additional cmdline arguments, you can skip it.

These files will be populated as you go through the rest of the tutorial.

  1. Create additional cmdline arguments for the new plugin by following Extending the SIERRA Cmdline For Your Plugin.

  2. Create the following filesystem structure in $HOME/git/plugins/fizzbuzz:

    Within plugin.py you must define a class named EXACTLY ExpDef and a module-level function named EXACTLY root_querypath(), otherwise SIERRA will not detect them. ExpDef derives from BaseExpDef and implements the modification interface described in the required interface below.

    import pathlib
    import typing as tp
    
    from sierra.core.experiment import definition
    
    
    def root_querypath() -> str:
        """Return a unique string identifying the root element for this file
        type. Needed when scaffolding batch experiments so SIERRA can do so in a
        format-agnostic way (e.g. ``"."`` for XML, ``"$"`` for JSON).
        """
        return "$"
    
    
    class ExpDef(definition.BaseExpDef):
        def __init__(
            self,
            input_fpath: pathlib.Path,
            write_config: tp.Optional[definition.WriterConfig] = None,
        ) -> None:
            ...
    
        # ... implement the required interface (see below) ...
    
  3. Put $HOME/git/plugins on your SIERRA_PLUGIN_PATH. Then your plugin can be selected as --expdef=plugins.fizzbuzz.