Our YAML module#

The swarmsim.yaml module provides a custom YAML loader that defines some convenience tags. This article will explain how the YAML files are loaded and how to use the custom tags.

See also

Looking for how to load or dump YAML files with our custom tags? See swarmsim.yaml

Or for information on how to use your custom class in a YAML file, see Config Registry.

YAML#

YAML is a human-readable data serialization format. We use it to write configurations that describe simulations.

It’s a superset of JSON, so it’s easy to read and write.

We use the PyYAML library to load and dump YAML files.

See also

Here’s a nice and quick tutorial for YAML: Learn YAML in Y minutes

Or have a look at the YAML specification

YAML Tags#

The YAML standard allows for !tags which provide information on how to parse a YAML entry. These tags usually start with ! and are defined in the YAML specification: Tags. An example of standard tags are type specifiers, such as !!str and !!int.

explicitly-typed-value: !!int 42

RobotSwarmSimulator uses a custom PyYAML loader to allow for some nice features. The custom YAML tags are defined in the yaml module.

Here’s an example of a crazy YAML file that uses a bunch of YAML features and our custom tags:

world.yaml (example)#
type: "RectangularWorld"
size: [10, 10]  # yaml flow style
agents:
- !include robot1.yaml  # add robot1 agent
- !include robot2.yaml  # add robot2 agent
- &anchor003  # save this robot as an anchor
  type: MazeAgent
  name: robot3
  agent_radius: 0.1
  angle: !np radians(90 + 45)  # convert degrees to radians
  poly: !include body_shape.svg  # load an SVG file
  controller:
    type: StaticController
    output: !np [1e-2, pi / 2]  # pi constant from numpy
spawners:
- type: ExcelSpawner
  path: !relpath positions.xlsx  # path is relative to cwd or this YAML file
  agent: *anchor003  # use the robot3 agent from above

If you’re new to YAML or haven’t seen the &anchor and *anchor syntax, check out Learn YAML in Y minutes.

To understand what the !include, !relpath, and !np tags do, read on.

The !np tag#

This tag is used to convert a YAML string, sequence, or mapping to a numpy object.

In this example, the following YAML files are in the same directory:

foo.yaml#
example: !np complex('2+2j')

See the mathexpr module for more information on what you can do.

The !include tag#

This tag is used to include another YAML file as a mapping.

For example, see the following YAML files:

bar.yaml#
my_list:
  - 1
  - 2
  - 3
foo.yaml#
foo: !include bar.yaml
Result#
>>> from swarmsim.yaml import load
>>> mapping = load('foo.yaml')

>>> print(mapping)
{'foo': {'my_list': [1, 2, 3]}}

The file extension of what you’re including affects the behavior of the !include tag:

  • .yaml files will be loaded using the load() function

  • .json files will be loaded using json.load

  • All other files are read as text and returned as a string

The !relpath tag#

This tag is used to resolve the relative path given, but unlike the !include tag, it does not load the file, and instead returns the absolute path as a string.

/home/user/project/foo.yaml#
path: !relpath bar.yaml

This is equivalent to:

path: /home/user/project/bar.yaml

Path Resolution Order#

When loading a YAML file, the !include and !relpath tags will resolve the path by testing the following assumptions in order:

  1. Path is not relative to the current working directory

    (i.e. the path is absolute or relative to the user home directory)

  2. Path is relative to the .yaml file with the tag

  3. Path is relative to the current working directory (where you were when you ran python).

    This is the default behavior for relative paths in Python, but it is the last place we look.

If a file isn’t found at any of these locations, an error will be raised. See include.search_file().